Dropdown menu

Lists the actions on one thing.

Items

  • actions, destructive lastdefault

  • labels, checkbox and radio

  • submenu

Sizes

  • defaultdefault

  • sm

Trigger

    • job_4812
    • job_4811
    • job_4810

    contextmenu

States

  • highlighted

  • destructive highlighted

  • disabled

  • checked

Usage

When to use it
Use
More actions on one thing than fit beside it: a job's replay, copy, open and cancel.
Use
A row's actions behind its More button, and the same list on a right click.
Use
View options for a table: which columns, which sort.
Not for
The person picks a value for a field. Use Select.
Not for
The person finds an action by typing. Use Command.
Not for
A few lines about the thing, not actions. Use Popover.

Rules

7 rules
Must
Start each item with a verb in sentence case, naming the object when the menu covers several; the row sets the capitals. Because an item is an action, and a label like "ID" does not say what pressing it does.
Must
Put a destructive item last, after a separator, with variant="destructive". Because the failure word and its tint mark the one item that loses work, and the rule keeps a slip of the arrow off it.
Must
Use DropdownMenuLinkItem for an item that goes to another page. Because a real link opens in a new tab and copies its address, which an onClick navigation cannot.
Must
Give every context menu a visible path too, usually the row's More button with the same items. Because a right click is invisible until tried, and a keyboard or touch user may never find it.
Should
Write a shortcut as keys="mod+c" on DropdownMenuShortcut. Because Kbd writes it for the reader's platform, Command on a Mac and Ctrl elsewhere.
Never
Fill a checked or chosen item with the selection wash or any colour; its ink check is the mark. Because three ticked rows in a seven-row menu became three yellow bands, which reads as noise, not state; the wash belongs to a selected table row.
Never
Add a shadow, padding or a rounded corner to DropdownMenuContent. Because Sodium has no shadows, only rules, and its rows run edge to edge so a highlighted row's lift and hairlines meet the edge.

State order

4 states, highest first
1
disabled
2
highlighted
3
checked
4
rest

Accessibility

6 checks
The trigger carries aria-haspopup="menu" and aria-expanded; the popup is role="menu".
The highlighted row lifts to white off the panel between two --line hairlines, in text-1 (18.3:1 and 13:1); that lift is the focus indicator, and forced colors draw a 2px outline.
A checked item shows an ink check in a fixed leading column and no fill, so unchecked items line up with it.
A disabled item stays reachable by arrows so its label is read; Enter does nothing.
Checkbox and radio items are menuitemcheckbox and menuitemradio with aria-checked.
A context menu takes its name through aria-label, since it has no trigger button.

Keyboard

5 keys
Enter, Space, Down
On the trigger: opens with the first item highlighted.
Up, Down, a letter
Moves the highlight; a letter jumps to the next item starting with it.
Right, Left
Opens and closes a submenu, mirrored in right to left.
Shift+F10
Opens a context menu at the focused row.
Escape
Closes this menu only and returns focus to the trigger.

Edge cases

6 edge cases
Long item label
Wraps inside the popup, which stops at the available width.
Forty items
The popup scrolls past 320px; group them with labels, or use a Command.
Near a viewport edge
It flips or shifts to stay 8px inside.
Touch
A long press opens the context menu without selecting a word.
Failed action
Report it after the menu closes; the menu has no error state.
Reduced motion
It cuts in and out.

API

8 props
DropdownMenu trigger
'click' | 'contextmenu' default 'click'
DropdownMenu onTargetChange
(row: HTMLElement | null) => void
DropdownMenuTrigger selectable
boolean default false
DropdownMenuContent size
'default' | 'sm' default 'default'
DropdownMenuItem variant
'default' | 'destructive' default 'default'
DropdownMenuItem inset
boolean default false
DropdownMenuShortcut keys
string
DropdownMenuCheckboxItem, RadioItem
Base UI

Tokens

23 tokens
--panel
#fafaf7
--line
#e2dfd5
--row-highlight
#ffffff
--row-highlight-edge
var(--line)
--field-inset
10px
--field-inset-sm
7px
--menu-min
192px
--popup-max
320px
--row-sm
32px
--control-sm
26px
--selected
#fff4bf
--fail-tint
#fdecea
--fail-text
#b3261e
--type-label
400 13px/16px var(--font-mono)
--type-label-sm
400 12px/16px var(--font-mono)
--type-micro
400 11px/14px var(--font-mono)
--text-1
#161512
--text-3
#6b675e
--text-disabled
#a8a499
--icon
16px
--z-overlay
50
--dur-overlay
160ms
--dur-state
120ms

Install

For your coding agent

GitHub

Please star me pookie

198

A new design system every week

Leave your email before you copy the prompt.