Dropdown Menu
Displays a menu of actions or options to the user.
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
- Right-click contextual actions - use Context Menu
- Searchable action palette - use Command
- Rich interactive content in a floating panel - use Popover
- Persistent navigation menus - use Navigation Menu or Menubar
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"androle="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-labelon 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>Related Components
Context Menu
Right-click contextual menu with the same item types and keyboard navigation.
Command
Searchable command palette for actions, navigation, and filtering.
Popover
Floating panel for rich interactive content like forms or custom layouts.
Menubar
Persistent horizontal menu bar for desktop-style application navigation.
API Reference
The Dropdown Menu is composed of several sub-components. Below are the most commonly used props for each.
DropdownMenu (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
| modal | boolean | true | Whether the menu should be modal. Set to false when opening dialogs from within the menu. |
| open | boolean | — | Controlled open state of the menu. |
| onOpenChange | (open: boolean) => void | — | Callback invoked when the open state changes. |
| defaultOpen | boolean | false | The initial open state for uncontrolled usage. |
DropdownMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
| 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. |
| sideOffset | number | 4 | Distance in pixels between the content and the trigger. |
| alignOffset | number | 0 | Horizontal offset in pixels from the alignment edge. |
| className | string | — | Additional CSS classes to apply to the content container. |
DropdownMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | "default" | "destructive" | "default" | The visual style variant. Destructive items use warning colors for dangerous actions. |
| inset | boolean | false | Adds left padding to visually align with checkbox or radio items. |
| disabled | boolean | false | When true, prevents interaction and applies disabled styling. |
| onSelect | (event: Event) => void | — | Callback invoked when the item is selected via click or keyboard. |
DropdownMenuCheckboxItem
| Prop | Type | Default | Description |
|---|---|---|---|
| checked | boolean | false | The controlled checked state of the checkbox item. |
| onCheckedChange | (checked: boolean) => void | — | Callback invoked when the checked state changes. |
| disabled | boolean | false | When true, prevents interaction and applies disabled styling. |
DropdownMenuRadioGroup
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | — | The controlled value of the selected radio item. |
| onValueChange | (value: string) => void | — | Callback invoked when the selected radio item changes. |