DropdownMenu
Default
Disabled item
Alignment and side
Above or below the trigger, start and end line up the left and right edges (mirrored in right-to-left text); beside it, on the left or right side, start lines up the top edges and end the bottom edges. A surface that flips to the other side keeps its alignment. It always stays at least 16 px inside the screen edges: where an aligned surface would run off the screen, it slides along the trigger instead; a tall surface is capped 16 px from the top or bottom; and beside the trigger it stops 16 px short of the far screen edge.
Long and many items
Labels and identifiers wrap and the rows grow; keep an identifier's own case by wrapping it in <code>, and give the item a textValue for typeahead when its children are not plain text. The menu is about 30rem wide at most and never wider than the screen. When the items are taller than the space beside the trigger, the menu scrolls inside itself instead of covering the trigger.
Danger items
danger colors the item and adds a written “Destructive action” line, so the warning does not rely on color. ContextMenu shows danger items the same way.
Keeping the menu open
onSelect receives a cancelable event. Call event.preventDefault() to keep the menu open after the item runs, for example for a toggle the operator may change again.
<DropdownMenuItem
onSelect={(event) => {
togglePin();
event.preventDefault();
}}
>
PIN TRACK
</DropdownMenuItem>
trigger takes one focusable element that forwards its ref and handlers, such as a Button; plain text renders as a secondary Button.
Motion
The popup arrives from its trigger in 200ms and exits in 150ms, with a small directional movement and scale. Selection and callbacks update immediately. Keyboard navigation, Escape, assistive activation, and system reduced motion stay instant. Use motion="none" to disable the treatment.
Props
| PROP | TYPE | DEFAULT | REQUIRED |
|---|---|---|---|
motionTactile pointer arrival and exit; keyboard, assistive activation, and system reduced motion remain immediate. | enumauto | none | "auto" | no |
triggerOne focusable element that forwards its ref and handlers, such as a Button; plain text renders a secondary Button. | node | — | yes |
open | boolean | — | no |
defaultOpen | boolean | — | no |
onOpenChange | function | — | no |
align | enumstart | center | end | "start" | no |
side | enumtop | right | bottom | left | "bottom" | no |
DropdownMenuItem
| PROP | TYPE | DEFAULT | REQUIRED |
|---|---|---|---|
shortcutDisplay text for an application-owned shortcut; it describes the item. | string | — | no |
dangerColors the item and adds a written “Destructive action” description. | boolean | false | no |
disabled | boolean | false | no |
textValuePlain text for typeahead when children are not a string (for example a <code> ID). | string | — | no |
onSelectReceives a cancelable event; call event.preventDefault() to keep the menu open. | function | — | no |
DropdownMenuLabel
DropdownMenuLabel takes no props of its own, only its text and native div attributes.
<DropdownMenuLabel>ACTIONS</DropdownMenuLabel>View agent manifest
{
"description": "Non-interactive uppercase section heading inside a DropdownMenu.",
"props": {},
"composable_with": [
"DropdownMenu"
],
"never_inside": [
"Button",
"Badge"
],
"example": "<DropdownMenuLabel>ACTIONS</DropdownMenuLabel>"
}DropdownMenuSeparator
DropdownMenuSeparator takes no props of its own, only native div attributes.
<DropdownMenuSeparator />View agent manifest
{
"description": "Thin horizontal rule grouping items inside a DropdownMenu.",
"props": {},
"composable_with": [
"DropdownMenu"
],
"never_inside": [
"Button",
"Badge"
],
"example": "<DropdownMenuSeparator />"
}Accessibility
- Enter/Space toggles; Arrow keys navigate; Escape closes.
menu/menuitemroles; disabled items are skipped and cannot be selected.- An item is named by its label and described by its shortcut and, for danger items, the written “Destructive action” cue.
- Give danger actions explicit labels as well.
Manifest entry
<DropdownMenu trigger={<Button variant="secondary">ACTIONS</Button>}>
<DropdownMenuLabel>ACTIONS</DropdownMenuLabel>
<DropdownMenuItem shortcut="⌘C">COPY</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem danger>DELETE</DropdownMenuItem>
</DropdownMenu>View agent manifest
{
"description": "Portal'd action menu anchored to a trigger element. Holds DropdownMenuItem, DropdownMenuSeparator, and DropdownMenuLabel children.",
"props": {
"motion": {
"type": "enum",
"values": [
"auto",
"none"
],
"default": "auto",
"description": "Tactile pointer arrival and exit; keyboard, assistive activation, and system reduced motion remain immediate."
},
"trigger": {
"type": "node",
"required": true,
"description": "One focusable element that forwards its ref and handlers, such as a Button; plain text renders a secondary Button."
},
"open": {
"type": "boolean"
},
"defaultOpen": {
"type": "boolean"
},
"onOpenChange": {
"type": "function"
},
"align": {
"type": "enum",
"values": [
"start",
"center",
"end"
],
"default": "start"
},
"side": {
"type": "enum",
"values": [
"top",
"right",
"bottom",
"left"
],
"default": "bottom"
}
},
"slots": {
"children": {
"type": "DropdownMenuItem | DropdownMenuSeparator | DropdownMenuLabel",
"required": true
}
},
"composable_with": [
"Toolbar",
"CardHeader"
],
"never_inside": [
"Button",
"Badge"
],
"example": "<DropdownMenu trigger={<Button variant=\"secondary\">ACTIONS</Button>}>\n <DropdownMenuLabel>ACTIONS</DropdownMenuLabel>\n <DropdownMenuItem shortcut=\"⌘C\">COPY</DropdownMenuItem>\n <DropdownMenuSeparator />\n <DropdownMenuItem danger>DELETE</DropdownMenuItem>\n</DropdownMenu>"
}