Dropdown Menu
A menu of actions displayed to the user when a trigger is activated. Supports items, checkboxes, radio groups, sub-menus, and keyboard shortcuts.
Installation
pnpm dlx @hex-core/cli add dropdown-menuGrouped row actions with a destructive item
Use DropdownMenuGroup + DropdownMenuLabel to cluster related actions, separators between clusters, and a danger-styled final item
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" aria-label="Row actions">…</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-56">
<DropdownMenuLabel>Quick actions</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem onSelect={() => onOpen(row.id)}>
Open
<DropdownMenuShortcut>↵</DropdownMenuShortcut>
</DropdownMenuItem>
<DropdownMenuItem onSelect={() => onDuplicate(row.id)}>
Duplicate
<DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuLabel>Sharing</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem onSelect={() => onCopyLink(row.id)}>Copy link</DropdownMenuItem>
<DropdownMenuItem onSelect={() => onShare(row.id)}>Invite people…</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-destructive" onSelect={() => onDelete(row.id)}>
Delete
<DropdownMenuShortcut>⌫</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>With checkbox + radio items
Toggle a side panel with DropdownMenuCheckboxItem and pick a single position with a DropdownMenuRadioGroup
const [showPanel, setShowPanel] = useState(true);
const [position, setPosition] = useState("right");
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline">View</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56">
<DropdownMenuLabel>Layout</DropdownMenuLabel>
<DropdownMenuCheckboxItem checked={showPanel} onCheckedChange={setShowPanel}>
Show panel
</DropdownMenuCheckboxItem>
<DropdownMenuSeparator />
<DropdownMenuLabel>Panel position</DropdownMenuLabel>
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="left">Left</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>
</DropdownMenu>
);API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Default open state |
onOpenChange | function | — | Callback on open state change: (open: boolean) => void |
modal | boolean | true | When true, interaction outside the menu is blocked |
AI Guidance
When to use
Use for action menus triggered by a button: user menus, row-action menus, toolbar overflow. Include DropdownMenuLabel for context, DropdownMenuSeparator for grouping.
When not to use
Don't use for navigation between pages (use NavigationMenu or links). Don't use for selection inputs (use Select or Combobox). Don't use for right-click menus (use ContextMenu).
Common mistakes
- Using DropdownMenu as a form Select (use Select instead)
- Putting interactive elements directly in the trigger without asChild
- Too many items without grouping (use DropdownMenuLabel + DropdownMenuSeparator)
- Forgetting DropdownMenuShortcut for keyboard-accessible actions
Accessibility
Full keyboard navigation: arrow keys, Home, End, typeahead, Escape. Radix handles role='menu', role='menuitem', and aria-labelledby.
Related components
Token budget: 700
Verified against @hex-core/components@1.12.0