Appica UIUI 1.0.0

Dropdown Menu

A button that opens a menu of actions and options.

Usage

Unlike a plain <button>, the trigger is wired to the menu through render — pass it your own Button (or any element) and the menu manages its aria-expanded, focus, and open/close. Every part lives in its own import under @appica/ui-react/dropdown-menu.

DropdownMenu is a compound component built on Base UI's Menu. The root holds the open state and the shared size; the parts compose the trigger and the portalled popup:

  • DropdownMenuTrigger — the button that toggles the menu. Use render to project it onto your own Button (or any element).
  • DropdownMenuContent — the portalled, auto-positioned popup. Accepts the shared floating props (side, align, sideOffset, …).
  • DropdownMenuItem — one action. Fires onClick and closes the menu by default.
  • DropdownMenuGroup / DropdownMenuGroupLabel / DropdownMenuSeparator — optional structure for sectioned lists.
  • DropdownMenuCheckboxItem / DropdownMenuRadioGroup + DropdownMenuRadioItem — stateful options with a check indicator.
  • DropdownMenuLinkItem — an item that renders an <a> for navigation.
  • DropdownMenuSub / DropdownMenuSubTrigger / DropdownMenuSubContent — a nested submenu.

Put a leading icon on data-icon="start" so the item reserves the right padding; push a trailing badge, Kbd shortcut, or icon to the far edge with ms-auto.

Reach for a DropdownMenu for actions triggered from a button. To pick one value from a list of options, use a Select; for the application command bar across the top of a window, use a Menubar; to open the same menu on right-click, use a Context Menu.

Examples

Account menu

A complete profile menu: a header with an Avatar, name, and a role Badge; grouped sections with count badges; a Settings submenu; an inline dark-mode Switch; and a sign-out action. The header is plain markup — only the rows that should be focusable are DropdownMenuItems.

Icons, shortcuts & animated chevron

Give items a leading icon with data-icon="start", and align a trailing Kbd shortcut with ms-auto. The trigger carries an animated chevron: mark the trigger group/trigger and add group-data-popup-open/trigger:rotate-180 to the icon so it flips while the menu is open. Paint a destructive action by overriding the item's text and highlight colors.

Groups & labels

Wrap related items in DropdownMenuGroup with a DropdownMenuGroupLabel, and split sections with DropdownMenuSeparator.

Scrollable

For a long list, cap the height and wrap the items in a ScrollArea for the custom scrollbar. Pull the ScrollArea out to the popup edges with -mx-2 (cancelling the popup's inner padding) and restore the item padding on the viewport (viewportProps={{ className: 'px-2' }}), so the scrollbar sits a hair inside the popup edge.

Checkbox items (controlled)

DropdownMenuCheckboxItem toggles a boolean and shows a check when on. Drive it with checked + onCheckedChange (or leave it uncontrolled with defaultChecked); checkbox items keep the menu open so several can be toggled in one pass. A classic real-world use is column visibility — each item controls whether a Table column is shown.

Radio items

Wrap mutually exclusive options in a DropdownMenuRadioGroup (controlled with value + onValueChange, or uncontrolled with defaultValue); each DropdownMenuRadioItem carries the value it selects. Like checkbox items, radio items keep the menu open after a choice.

Nest a DropdownMenuSub with its own DropdownMenuSubTrigger and DropdownMenuSubContent. The trigger shows a chevron and opens on hover or with the arrow keys; the submenu opens to the side and flips automatically near a screen edge.

Open on hover

Set openOnHover on the DropdownMenuTrigger to open the menu when the pointer rests on it (it still opens on click and keyboard too). Tune the timing with delay / closeDelay. Use this sparingly — hover menus aren't reachable on touch and can feel twitchy.

DropdownMenuLinkItem renders a real <a>, so it navigates (and supports target, modifier-clicks, and right-click "open in new tab") while staying keyboard-reachable inside the menu. For internal routes, project it onto your router's link via render — here a Next.js Link (render={<Link href="…" />}) for client-side navigation; for external links, pass a plain href with target="_blank".

Sizes

size on the root scales the popup radius, item padding, and icon size together — sm, md (default), or lg.

Side & alignment

Position the popup with side (top / right / bottom / left) and align (start / center / end) on DropdownMenuContent. It still flips and shifts automatically to stay in view.

By default a menu only flips to the opposite same-axis side (e.g. rightleft); it won't re-place onto the other axis, since menus cap their height and scroll instead. For a side-opening (left / right) menu, pass collisionAvoidance={{ fallbackAxisSide: 'end' }} so it can fall back to the top/bottom axis when neither side fits — that's why the left and right triggers below set it.

RTL

Every Appica UI component supports right-to-left layouts out of the box. Set the dir attribute on a container (commonly your <html> element) so CSS logical properties resolve correctly, and wrap your tree in DirectionProvider so direction-aware behavior — roving focus, popup placement, and submenu direction — follows the same direction.

The popup anchors from the trigger's leading edge, submenus open toward the inline-start side, and the submenu chevron mirrors. For setup details and caveats, see the RTL guide.

API reference

DropdownMenu wraps Base UI's Menu. Each part forwards every remaining prop to the matching Base UI primitive, so anything it accepts works here — the tables below list the Appica additions and the most common props. See the Base UI docs for the complete API.

The root. Holds the open state and the shared size; renders no DOM of its own.

The button that toggles the menu. Forwards Base UI's Menu.Trigger; use render to project it onto your own element.

The portalled, auto-positioned popup wrapping the list. Defaults to align="start" and sideOffset={6}, and accepts the shared floating props.

One action in the menu.

A toggleable item with a check indicator. Keeps the menu open on click.

Wraps a set of mutually exclusive DropdownMenuRadioItems.

One option in a DropdownMenuRadioGroup. Keeps the menu open on click.

An item that renders an <a> for navigation. Forwards every native anchor prop (href, target, rel, …).

Wraps a nested submenu. Forwards Base UI's Menu.SubmenuRoot.

The item that opens a submenu; renders a trailing chevron. Submenus open on hover by default.

The submenu popup. Defaults to opening on the inline-end side; otherwise identical to DropdownMenuContent.

Wraps one labelled section of items so a DropdownMenuGroupLabel can name it.

The visible heading for a DropdownMenuGroup. Size-aware; must be rendered inside a DropdownMenuGroup (or DropdownMenuRadioGroup).

A thin divider between items or groups.

Accessibility

  • The trigger is a button with aria-haspopup="menu" and aria-expanded; the popup has role="menu" and items are menuitem, menuitemcheckbox, or menuitemradio.
  • Enter / Space / ↓ open the menu, ↑/↓ move the highlight, opens a submenu, closes it, Enter selects, Escape closes, and typing jumps to the matching item (typeahead).
  • Focus is trapped inside the open popup when modal (the default) and returns to the trigger on close.
  • disabled items are skipped by keyboard navigation and typeahead.
  • DropdownMenuLinkItem keeps native anchor semantics, so links are announced and openable in a new tab.
  • Popup enter/exit transitions are skipped when the user prefers reduced motion.

© 2026 Appica UI. A free component library, crafted by the Appica team.