Dropdown menu
Opens a menu of actions or options from a button, like a record's row actions.
Installation
pnpm dlx shadcn@latest add @wisty/dropdown-menu
The CLI installs the Radix or Base UI file to match your project.
If your project doesn't have Wisty UI's theme yet, add it once with npx shadcn@latest add @wisty/cosmos. Until then, components keep shadcn's default look. Installation has the details.
When to use
Use it
- A button opens a list of actions, like a record's Edit, Clone and Delete.
- Row actions in a table, behind a small icon button.
- A few settings that change a view, like visible columns (checkbox items) or a sort order (radio items).
Don't use it
- People pick a value for a form field. Use Select.
- People search a long list. Use Combobox.
- There are only one or two actions with room for them. Show buttons.
- The list is navigation between pages. Use links or Tabs.
- People right-click an object to act on it. Use Context menu.
Usage
DropdownMenu
├── DropdownMenuTrigger
└── DropdownMenuContent
├── DropdownMenuGroup
│ ├── DropdownMenuLabel
│ └── DropdownMenuItem
│ └── DropdownMenuShortcut
├── DropdownMenuSeparator
└── DropdownMenuSub
├── DropdownMenuSubTrigger
└── DropdownMenuSubContent
└── DropdownMenuItemimport { buttonVariants } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"<DropdownMenu>
<DropdownMenuTrigger className={buttonVariants({ variant: "outline" })}>
New
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem onClick={newOpportunity}>Opportunity</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>- Run an action with
onClick, which works in Radix and Base UI projects;onSelectis Radix only. - For settings, use
DropdownMenuCheckboxItem, orDropdownMenuRadioIteminside aDropdownMenuRadioGroup, in an item's place.inseton an item, label or submenu trigger indents its text to line up with theirs. - In Radix projects, checking a checkbox or radio item closes the menu; call
event.preventDefault()in itsonSelectto keep it open. In Base UI projects the menu stays open; passcloseOnClickto close it.
Examples
Row actions
An opportunity row's actions behind a small icon button named for the row, the menu lined up with its end by `align="end"`.
Acme - 200 Widgets
Prospecting · $120,000
Checkbox and radio items
Checkbox items (`DropdownMenuCheckboxItem`) for visible columns and radio items (`DropdownMenuRadioItem`) for the sort order, one checked in each.
API reference
DropdownMenu
| Prop | Type | Default |
|---|---|---|
modal | boolean | false |
DropdownMenuContent
| Prop | Type | Default |
|---|---|---|
align | "center" | "end" | "start" | "start" |
sideOffset | number | 2 |
DropdownMenuItem
| Prop | Type | Default |
|---|---|---|
inset | boolean | |
variant | "default" | "destructive" | "default" |
DropdownMenuCheckboxItem
| Prop | Type | Default |
|---|---|---|
inset | boolean |
DropdownMenuRadioItem
| Prop | Type | Default |
|---|---|---|
inset | boolean |
DropdownMenuLabel
| Prop | Type | Default |
|---|---|---|
inset | boolean |
DropdownMenuSubTrigger
| Prop | Type | Default |
|---|---|---|
inset | boolean |
DropdownMenuSubContent
| Prop | Type | Default |
|---|---|---|
sideOffset | number | 4 |
SLDS mapping
DropdownMenuContentandDropdownMenuSubContentareslds-dropdown.DropdownMenuItem,DropdownMenuCheckboxItemandDropdownMenuRadioItemareslds-dropdown__item. Checked items show SLDS's selected check (slds-icon_selected) before the text.DropdownMenuLabelisslds-dropdown__header.DropdownMenuSeparatorisslds-has-divider_top-space.DropdownMenuSubTriggeris an item withslds-has-submenu.DropdownMenuShortcuthas no SLDS counterpart. The trigger is whatever you style it as, usually Button's neutral or icon button.
Known gaps:
- No nubbin, and no
slds-dropdown_length-*heights. The menu scrolls only when it runs out of room on screen. - Icons are lucide's, not SLDS's utility icons.
- SLDS truncates a long item on one line. Here it wraps, unless you wrap the label in
<span className="truncate">. - A submenu trigger keeps its highlight while its submenu is open. SLDS drops it once focus moves into the submenu.
| Prop | Value | SLDS | Notes |
|---|---|---|---|
DropdownMenuItem variant | default | slds-dropdown__item | |
DropdownMenuItem variant | destructive | none | SLDS has no destructive item. The text and icon take the error color; the highlight stays. |
DropdownMenuItem inset | true | none | Starts the text where a checked item's text starts. |
Keyboard interactions
| Keys | Action |
|---|---|
| Enter, Space or Down Arrow | On the trigger, opens the menu and focuses the first item. |
| Down Arrow, Up Arrow | Moves focus to the next or previous item. |
| Home, End | Moves focus to the first or last item. |
| Letters | Moves focus to the next item that starts with them. |
| Enter or Space | Runs the focused item, or checks it. |
| Right Arrow | On a submenu trigger, opens the submenu and focuses its first item. |
| Left Arrow | In a submenu, closes it and returns focus to its trigger. |
| Escape | Closes the menu and returns focus to the trigger. |
In Radix projects the arrow keys skip disabled items. In Base UI projects focus lands on them, but Enter and Space don't run them.
Accessibility
- Name an icon-only trigger with
aria-label. In a list, name it for its row ("Show actions for Acme"), as the Row actions example does, so screen readers can tell the buttons apart. - A disabled item still reads out. Say why it's unavailable in nearby text if it matters.
Responsive behavior
- The menu is as wide as its longest item, between 6rem and 20rem.
- For a menu at the end of a row, pass
align="end"to line it up with the trigger's end edge, as the Row actions example does.
Rules
- Put each
DropdownMenuLabelinside aDropdownMenuGroup, or the menu can throw. - Pass
modalonly when the page must be blocked. A modal menu stops the page scrolling and takes the next click outside just to close itself. - Never nest a Button inside the trigger. That's a button in a button; style the trigger with
buttonVariants()instead. - Put an icon first in an item, then the text, then an optional
DropdownMenuShortcut. The shortcut only shows the keys; it doesn't make them work. - Use
variant="destructive"only for actions that delete or can't be undone, and put them last, after a separator. - Don't restyle highlight, focus or check colors. They come from the theme tokens.