GitHubnpm

Accent theme

Base radius

GitHubnpm

Accent theme

Base radius

Colour scheme

Docs menu

Guides


Primitives
Forms
Layout
Feedback
Overlays
Navigation
Data Display
AI

Dropdown Menu

role="menu" on a popover="auto" element. Outside-click and Escape dismissal come free from the popover. Arrow-key roving between items is the one part of the WAI-ARIA menu pattern that has to be wired up by hand, there's no native menu element yet. A morph variant further down grows the panel out of its own trigger instead of fading in place.

Usage
import { Button, DropdownMenu, MenuChevron, MenuItem, MenuSeparator } from "@kernelui-lib/react";

function ActionsMenu() {
  return (
    <DropdownMenu
      align="end"
      offset={4}
      className="my-menu"
      render={<Button variant="secondary" iconEnd={<MenuChevron />}>Actions</Button>}
    >
      <MenuItem onSelect={() => {}}>Edit</MenuItem>
      <MenuItem render={<a href="/docs" />}>Documentation</MenuItem>
      <MenuSeparator />
      <MenuItem destructive onSelect={() => {}}>
        Delete
      </MenuItem>
    </DropdownMenu>
  );
}

Playground

Toggle every adjustable prop and watch the component — and the code — update live.

Unstyled

Same component — Kernel look stripped. See Platforms.

placement
align
delete item destructive
duplicate item disabled
Usage
<DropdownMenu render={<Button variant="secondary" iconEnd={<MenuChevron />}>Actions</Button>}>
  <MenuItem onSelect={() => {}}>Edit</MenuItem>
  <MenuItem onSelect={() => {}}>Duplicate</MenuItem>
  <MenuSeparator />
  <MenuItem destructive onSelect={() => {}}>
    Delete
  </MenuItem>
</DropdownMenu>

Props

Props for Dropdown Menu.
ComponentPropType
DropdownMenurenderthe trigger (required)
DropdownMenurenderContentRenderProp — replace the popup
DropdownMenuclassNamestring | (state) => string
DropdownMenuplacement"top" | "bottom" | "left" | "right"
DropdownMenualign"start" | "center" | "end"
DropdownMenuoffsetnumber (px)
MenuItemrenderRenderProp — e.g. <a> / router Link
MenuItemclassNamestring | (state) => string
MenuItemonSelect() => void
MenuItemdestructiveboolean
MenuChevronno props — drop into a trigger's iconEnd; rotates via aria-expanded
DropdownMenuMorphrenderthe trigger (required) — same shape as DropdownMenu's
DropdownMenuMorphrenderContentRenderProp — replace the popup
DropdownMenuMorphclassNamestring | (state) => string
DropdownMenuMorphplacement"top" | "bottom" | "left" | "right"
DropdownMenuMorphalign"start" | "center" | "end"
DropdownMenuMorphoffsetnumber (px)

Morph variant

DropdownMenuMorph is the same menu — it sharesMenuItem/MenuSeparator directly — with a different opening move: the panel's own box grows out of the trigger's exact footprint (width, height, and corner radius all animate) instead of scaling and fading in place.

That one visual difference forces a mechanical one: a popover's hide can't be deferred, so there's no way to let the shrink-back- to-the-trigger animation finish before the panel actually disappears while staying popover="auto". This variant is popover="manual" instead, with its own outside- click and Escape dismissal wired up by hand — the same tradeoffContextMenu and Combobox already make for their own manual popovers. Selecting an item still plays the full shrink animation before the menu closes.

The trigger's own icon rotation/cross-fade (the + that becomes a × below) is authored in the demo, not baked into the component — same convention as MenuChevron: what renders is always visible at the call site.

Usage
import { DropdownMenuMorph, MenuItem, MenuSeparator } from "@kernelui-lib/react";

<DropdownMenuMorph render={<PlusTrigger />}>
  <MenuItem onSelect={() => {}}>New file</MenuItem>
  <MenuItem onSelect={() => {}}>New folder</MenuItem>
  <MenuSeparator />
  <MenuItem onSelect={() => {}}>Upload</MenuItem>
</DropdownMenuMorph>

Accessibility

Opening moves focus to the first item. Arrow Up/Down, Home, and End move between items. Selecting an item, or pressing Escape, closes the menu. Link items keep native navigation, modifier-clicks, and new-tab behaviour — selection closes the menu withoutpreventDefault.