Menus/Dropdown Menu

Dropdown Menu

Displays a menu of actions or options to the user.

Themed

When to Use

Use Dropdown Menu when you need to:

  • Present a list of actions or options triggered by a button click
  • Group related actions behind a single trigger to reduce UI clutter
  • Offer checkbox or radio selection within a transient menu
  • Organize complex actions with submenus, labels, and separators
  • Display keyboard shortcut hints alongside menu items

When Not to Use

Default

Full-featured dropdown menu with groups, submenus, and keyboard shortcuts.

With Icons

Menu items with leading icons and a destructive variant for dangerous actions.

Checkboxes

Menu with selectable checkbox items for toggling multiple options independently.

Radio Group

Menu with radio items for single-selection among mutually exclusive options.

Submenu

Nested submenus for organizing hierarchical actions. Opens on hover or arrow key.

// Use modal={false} to prevent focus issues when
// opening a dialog from within a dropdown menu.
<DropdownMenu modal={false}>
  <DropdownMenuTrigger asChild>
    <Button variant="outline">Actions</Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuItem onSelect={() => setDialogOpen(true)}>
      Open Dialog...
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

UX & Design Guidelines

Visual Hierarchy

Use DropdownMenuLabel to title groups of related items. Place the most common actions at the top of the menu. Use DropdownMenuSeparator to create clear visual boundaries between groups. Reserve variant="destructive" for irreversible actions and position them at the bottom of the menu.

Spacing & Layout

Set a consistent width using className="w-56" (224px) for standard menus. Use align="start" or align="end" to align the menu with the trigger edge. Avoid deeply nested submenus (two levels maximum) to prevent user disorientation.

Responsive Behavior

The menu automatically flips to the opposite side when there is insufficient viewport space. On mobile, consider using a Drawer or Sheet instead for complex option lists, as nested submenus can be difficult to navigate on touch devices. Keep menus concise (7 items or fewer per group).

Color & Contrast

Menu items use bg-popover with text-popover-foreground for clear readability. Focus and hover states apply bg-accent with text-accent-foreground for strong visual feedback. Disabled items reduce opacity to 50% while maintaining legibility.

Accessibility

Keyboard Navigation

  • Enter or Space — Open the menu from the trigger, or select the focused item
  • Arrow Down / Arrow Up — Move focus between menu items
  • Arrow Right — Open a submenu when focused on a sub-trigger
  • Arrow Left — Close the current submenu and return to the parent
  • Escape — Close the menu and return focus to the trigger

Screen Reader Support

  • Uses role="menu" and role="menuitem" for proper semantics
  • Checkbox items announce their checked/unchecked state via role="menuitemcheckbox"
  • Radio items announce their selected state via role="menuitemradio"
  • Disabled items are announced as unavailable via aria-disabled
  • Icon-only triggers require aria-label on the trigger button

Focus Management

When the menu opens, focus moves to the first enabled item automatically. When closed via Escape or item selection, focus returns to the trigger element. Submenus manage their own focus independently, preserving the parent menu's focus position on close.

Type-ahead Search

Typing characters while the menu is open will focus the first matching item by label. This allows rapid navigation in long menus without using arrow keys. Type-ahead resets after a short delay.

ARIA Attributes

{/* Trigger with accessible label */}
<DropdownMenu>
  <DropdownMenuTrigger asChild>
    <Button variant="outline" aria-label="User settings menu">
      <Settings className="size-4" />
    </Button>
  </DropdownMenuTrigger>
  <DropdownMenuContent>
    <DropdownMenuLabel>Settings</DropdownMenuLabel>
    <DropdownMenuSeparator />
    <DropdownMenuItem>Profile</DropdownMenuItem>
    <DropdownMenuItem>Preferences</DropdownMenuItem>
    <DropdownMenuSeparator />
    <DropdownMenuItem variant="destructive">
      Delete Account
    </DropdownMenuItem>
  </DropdownMenuContent>
</DropdownMenu>

{/* Disabled item with context */}
<DropdownMenuItem disabled aria-describedby="api-note">
  API Access
</DropdownMenuItem>
<span id="api-note" className="sr-only">
  Requires a paid plan to enable
</span>

API Reference

The Dropdown Menu is composed of several sub-components. Below are the most commonly used props for each.

DropdownMenu (Root)

PropTypeDefaultDescription
modalbooleantrueWhether the menu should be modal. Set to false when opening dialogs from within the menu.
openbooleanControlled open state of the menu.
onOpenChange(open: boolean) => voidCallback invoked when the open state changes.
defaultOpenbooleanfalseThe initial open state for uncontrolled usage.

DropdownMenuContent

PropTypeDefaultDescription
align"start" | "center" | "end""center"Horizontal alignment of the content relative to the trigger.
side"top" | "right" | "bottom" | "left""bottom"Preferred side of the trigger to render the content against.
sideOffsetnumber4Distance in pixels between the content and the trigger.
alignOffsetnumber0Horizontal offset in pixels from the alignment edge.
classNamestringAdditional CSS classes to apply to the content container.

DropdownMenuItem

PropTypeDefaultDescription
variant"default" | "destructive""default"The visual style variant. Destructive items use warning colors for dangerous actions.
insetbooleanfalseAdds left padding to visually align with checkbox or radio items.
disabledbooleanfalseWhen true, prevents interaction and applies disabled styling.
onSelect(event: Event) => voidCallback invoked when the item is selected via click or keyboard.

DropdownMenuCheckboxItem

PropTypeDefaultDescription
checkedbooleanfalseThe controlled checked state of the checkbox item.
onCheckedChange(checked: boolean) => voidCallback invoked when the checked state changes.
disabledbooleanfalseWhen true, prevents interaction and applies disabled styling.

DropdownMenuRadioGroup

PropTypeDefaultDescription
valuestringThe controlled value of the selected radio item.
onValueChange(value: string) => voidCallback invoked when the selected radio item changes.