Skip to content
HyperDesign System

Dropdown menu

A list of actions or options opened from a button. Full keyboard support from Radix: arrows, typeahead, submenus, Esc. Source: src/components/ui/dropdown-menu.tsx.

Groups, shortcuts and submenus

A label, grouped items with Tabler icons, Kbd shortcuts, a submenu, a disabled row and a destructive item set apart at the end.

selected: nothing yet

Checkbox and radio items

Checkbox items toggle independently; radio items pick one. Preventing onSelect keeps the menu open while several columns are toggled.

columns: Status, Owner, Last run · sort: recent

Custom indicator

indicator="none" removes the gutter so a richer row can show its own state, as the composer's model pill does.

Row actions

The overflow menu on a list row: an icon-sm ghost trigger with a specific aria-label, aligned to the end so it opens inward.

Weekly competitor digest

Keyboard

Dropdown menu keyboard map
KeyWhereDoes
Enter · SpaceOpen and focus the first item. ↓ opens too; ↑ opens on the last item.
↑ ↓Move between items, skipping disabled ones. Typing a letter jumps to a match.
→ ←Open the submenu and enter it / close it and return.
Enter · SpaceSelect. Checkbox and radio items toggle.
EscClose and return focus to the trigger.

Motion and layering

Asymmetric enter and exit on keyframes; under reduced motion the global rule cuts both to near-zero. Item highlight is a colour change only, so nothing shifts.

Dropdown menu motion and layering tokens
ValueTokenUsage
50Above the page, same layer as dialogs. The brand ladder (--z-dropdown 100) is defined but not wired in yet.
140msFade, scale from 95% out of the trigger, 8px slide.
90msFade and scale out, faster than the entrance.
100msItem highlight (tint-10 fill) as focus moves.
max-hLong menus scroll inside the viewport instead of overflowing it.

Props

Dropdown menu parts and props
Part / propTypeDefaultDescription
DropdownMenuRadix DropdownMenu.Root—open, defaultOpen, onOpenChange, modal (true: outside clicks are blocked while open).
DropdownMenuTriggerRadix DropdownMenu.Trigger—Use asChild around a Button. Gets aria-expanded, which Button styles.
DropdownMenuContentRadix DropdownMenu.Content—Portals itself. Takes side, align, loop. A pointer close leaves focus where it is; a keyboard close returns it to the trigger.
sideOffsetnumber4Gap from the trigger, in px.
DropdownMenuItemRadix DropdownMenu.Item—onSelect, disabled, textValue (for typeahead).
variant"default" | "destructive""default"Destructive turns text, icon and focus fill red.
insetbooleanfalse32px left padding to line up with iconed or checkable rows. Also on Label and SubTrigger.
DropdownMenuCheckboxItemRadix CheckboxItem—checked, onCheckedChange. role=menuitemcheckbox.
indicator"check" | "none""check"none drops the check gutter so the row shows its own state.
DropdownMenuRadioGroupRadix RadioGroup—value, onValueChange.
DropdownMenuRadioItemRadix RadioItem—value. role=menuitemradio.
indicator"dot" | "none""dot"none drops the dot gutter.
DropdownMenuLabelRadix Label—A non-interactive heading row; inset available.
DropdownMenuGroup, SeparatorRadix—Group related items; the separator is a hairline that bleeds to the edges.
DropdownMenuShortcutComponentProps<"span">—Right-aligned slot. Holds plain text or Kbd. Display only; it binds nothing.
DropdownMenuSub, SubTrigger, SubContentRadix—Nested menu. SubContent renders inline (no portal).
DropdownMenuPortalRadix Portal—Exported for custom shells; Content already portals.

Best practices

When to use

  • Actions or a single choice behind one button. A form value with a visible current state is a Select.
  • For the same actions on right-click, mirror them in a ContextMenu; the item styles are shared.
  • Search across many commands belongs in Command, not a long dropdown.

Behavior

  • Group with separators; put destructive items last, on their own.
  • Shortcuts are display only. Bind the key elsewhere and show the same combo here.
  • Keep submenus one level deep.

Accessibility

  • Icon-only triggers need an aria-label that names the object (“Actions for …”).
  • Icons inside items are aria-hidden; the text is the label.
  • Keyboard closes return focus to the trigger; pointer closes deliberately don't, to avoid a stray ring and tooltip.

Content

  • Verbs for actions (Rename, Delete), nouns for options (Name, Cost).
  • Explain a disabled item in its label, or remove it.