Menu
A list of actions in a native popover — opened by a popovertarget button, light-dismissed by the browser, arrow-key navigable with membrane.js.
Examples
Actions menu
HTML for “Actions menu”
<button class="mp-button" type="button" data-variant="secondary" popovertarget="menu-workshop" aria-haspopup="menu" aria-expanded="false">Workshop actions</button>
<div class="mp-menu" id="menu-workshop" popover role="menu" aria-label="Workshop actions">
<p class="mp-menu__label" role="presentation">Edit</p>
<button class="mp-menu__item" type="button" role="menuitem">
<svg class="mp-icon" viewBox="0 0 24 24" aria-hidden="true"><rect x="8" y="8" width="14" height="14" rx="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
Duplicate
</button>
<button class="mp-menu__item" type="button" role="menuitem">Export syllabus</button>
<button class="mp-menu__item" type="button" role="menuitem" aria-disabled="true">Move to cohort (none open)</button>
<hr class="mp-menu__separator">
<button class="mp-menu__item" type="button" role="menuitem" data-tone="danger">Archive workshop</button>
</div>
Guidance
For secondary actions that don't deserve permanent space: "Duplicate", "Export", "Archive". Built on the native popover attribute, so the browser handles opening, top-layer stacking, Escape and click-outside. components/membrane.js adds the WAI-ARIA menu keyboard pattern (↑/↓, Home/End, focus on open, return focus on close), keeps aria-expanded in sync and positions the menu in browsers without CSS anchor positioning.
When not to use
Accessibility
- The trigger has
popovertarget,aria-haspopup="menu"andaria-expanded(kept in sync bymembrane.js). - The popover has
role="menu"and anaria-label; items are<button role="menuitem">. Separators and group labels are presentational. - Keyboard (with
membrane.js): opening focuses the first item; ↑/↓ move, Home/End jump, Escape closes and returns focus to the trigger; choosing an item closes the menu. - Destructive items use
data-tone="danger"and a clear verb — color is never the only signal. Follow them with a confirmation Dialog.
Manual screen-reader and usability checks have not been recorded for this inventory. See the accessibility evidence for automated coverage, remaining checks and the result-recording protocol.
API
| Class | Kind |
|---|---|
.mp-menu | root |
.mp-menu__item | part of .mp-menu |
.mp-menu__separator | part of .mp-menu |
.mp-menu__label | part of .mp-menu |
| Attribute | Values |
|---|---|
data-tone | danger |
States styled: :disabled :focus-visible :hover :popover-open [aria-disabled="true"]. Set the native attribute or ARIA state; there are no state classes.
| Token | Default | Light · dark |
|---|---|---|
--mp-menu-bg | var(--color-bg-elevated) | #FAF6EE · #27272D |
--mp-menu-fg | var(--color-text-primary) | #2A2622 · #F0EBE1 |
--mp-menu-item-bg-hover | var(--color-bg-hover) | rgba(42, 38, 34, 0.06) · rgba(240, 235, 225, 0.06) |
--mp-menu-danger | var(--color-error-text) | #A53434 · #F07C78 |
--mp-menu-label | var(--color-text-tertiary) | #6E685F · #938D83 |
Design tokens consumed: --border-default --border-width-medium --border-width-thin --color-bg-elevated --color-bg-hover --color-border-default --color-error-text --color-text-primary --color-text-tertiary --duration-fast --duration-normal --elevation-overlay --focus-ring --font-sans --radius-md --radius-sm --size-control-sm --size-icon-sm --size-touch-target --space-1 --space-2 --space-3 --state-disabled-opacity --text-small --text-xs --tracking-label --transition-enter --transition-exit --weight-semibold
Verified contrast
The build measures each pair for the defaults and for every tone, variant and state that reassigns a token, over page and card surfaces. The ratios below are the worst case in each mode; a pair below its minimum stops the build.
| Use | Pair | Light | Dark | Minimum |
|---|---|---|---|---|
| menu item | --mp-menu-fg on --mp-menu-bg | 13.93 | 12.50 | 7.0 |
| menu item, focused | --mp-menu-fg on --mp-menu-item-bg-hover | 12.51 | 10.58 | 4.5 |
| danger item | --mp-menu-danger on --mp-menu-bg | 6.20 | 5.56 | 4.5 |
| group label | --mp-menu-label on --mp-menu-bg | 5.12 | 4.51 | 4.5 |