Menus
Last updated:
Practical patterns for dropdown action menus with keyboard support and clear labels.
01 — Foundation
Menus expose actions — not entire workflows
Dropdown menus work for secondary actions. They fail when they become hidden primary navigation.
Menus group related actions — row menus, profile menus, overflow controls. They must be keyboard operable, clearly labelled, and dismissible. For larger panels see Popovers; for site navigation see Navigation.
02 — Trigger
Triggers and labels
Users must know what the menu contains before it opens.
-
buttonwith accessible name — “Actions for invoice 1042”, not icon-only without label -
aria-expandedreflects open state;aria-controlspoints at the menu id -
menu items are
buttonora— notdivclick handlers
<button type="button" aria-expanded="false" aria-controls="row-menu" aria-haspopup="menu">
Actions
</button>
<ul id="row-menu" role="menu" hidden>
<li role="none"><button type="button" role="menuitem">Duplicate</button></li>
</ul> 03 — Keyboard
Keyboard and dismissal
Arrow keys, Enter, Escape, and focus return are not optional.
- arrow keys move between items; Escape closes and returns focus to the trigger
- do not close on focus moving to the first item in a broken way
- separate destructive items visually — see Destructive Actions
-
native
popoveror platform menu patterns where they meet requirements
04 — Review
Before you approve
A short checklist for menus in code review.
- labelled trigger; semantic menu items; expanded state exposed
- full keyboard support; focus returns on close
- touch targets adequate on mobile