Dropdown Menu
An accessible, keyboard-navigable menu of actions anchored to a trigger.
DropdownMenu displays a set of actions in a popout attached to a trigger. Its compound components support grouped actions, checkable options, and mutually exclusive choices.
Import
import { DropdownMenu } from "@puzzle-ui/ui";Basic usage
Every menu requires exactly one DropdownMenu.Trigger and one DropdownMenu.Content. asChild lets the trigger use a custom element, such as a Puzzle Button.
The root can be controlled with open and onOpenChange, or initialized with defaultOpen. When controlled, update open in response to onOpenChange. Set disabled on the root or trigger to prevent opening.
Groups, checkboxes, and radio choices
Use Group and Label to organize actions and Separator to divide sections. Checkbox items stay open by default so users can make multiple choices; radio items close the menu by default after selection.
Checkbox items can also use defaultChecked when uncontrolled. Radio groups accept defaultValue for an uncontrolled selection. checked="indeterminate" is available for a checkbox item to expose a mixed state.
Position and sizing
position requests a side of the trigger (top, right, bottom, or left); the popout may adjust when space is limited. align accepts start, center, or end. offset and collisionPadding are pixel values. Set matchTriggerWidth to make the content match the trigger width. Use DropdownMenu.Content's maxHeight to control its maximum height.
Keyboard interaction and accessibility
- The trigger exposes menu-button semantics and opens on click, Enter, Space, Arrow Down, or Arrow Up. Arrow Up opens with focus on the last enabled item; other opening actions focus the first.
- Within the menu, Arrow Up and Arrow Down move between enabled items; Home and End focus the first and last item. Typing characters moves focus by item text.
- Enter or Space activates the focused item. Escape closes the menu and restores focus to the trigger. Tab closes the menu and moves focus out of it.
- Disabled items cannot be activated or reached using menu navigation. Use
textValuewhen an item's visible content is not a suitable typeahead label. - Give the trigger a meaningful accessible name. The content is labelled by the trigger by default;
aria-labelcan provide a direct name onDropdownMenu.Content.
API
DropdownMenu
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | Required | One DropdownMenu.Trigger and one DropdownMenu.Content. |
open | boolean | - | Controlled visibility. |
defaultOpen | boolean | false | Initial visibility when uncontrolled. |
onOpenChange | (open: boolean) => void | - | Called when visibility changes are requested. |
disabled | boolean | false | Prevents opening the menu. |
position | "top" | "right" | "bottom" | "left" | "bottom" | Preferred side of the trigger. |
align | "start" | "center" | "end" | "start" | Alignment along the trigger. |
offset | number | 8 | Gap from the trigger in pixels. |
collisionPadding | number | 8 | Minimum space from the viewport edges in pixels. |
matchTriggerWidth | boolean | false | Match the content width to the trigger. |
triggerClassName, contentClassName | string | - | Additional classes on the trigger or content. |
Compound components
| Component | Key props | Description |
|---|---|---|
DropdownMenu.Trigger | asChild, disabled, standard button props | Trigger button. With asChild, composes its behavior onto one child element. |
DropdownMenu.Content | maxHeight, aria-label, aria-labelledby, standard div props | Menu panel; labelled by the trigger unless aria-label is provided. |
DropdownMenu.Item | asChild, disabled, textValue, closeOnSelect, variant, onSelect | Action item. variant="danger" emphasizes destructive actions. By default, selection closes the menu; prevent the event's default action in onSelect to keep it open. |
DropdownMenu.Group | aria-label, standard div props | Groups related menu items. |
DropdownMenu.Label | children, standard div props | Text label for a section. |
DropdownMenu.Separator | standard div props | Horizontal separator between sections. |
DropdownMenu.CheckboxItem | checked, defaultChecked, onCheckedChange, closeOnSelect, disabled, textValue, onSelect | Checkable option. Uncontrolled by default; does not close on selection unless closeOnSelect is set. |
DropdownMenu.RadioGroup | value, defaultValue, onValueChange | Holds mutually exclusive radio items. |
DropdownMenu.RadioItem | value, closeOnSelect, disabled, textValue, onSelect | Choice within a radio group; closes on selection by default. |
Items also accept standard button attributes, and groups, labels, separators, and content accept standard div attributes. Item onSelect receives the triggering mouse event. Each item supports textValue for keyboard typeahead when its text content is unsuitable.