Menu
An action menu surfaces a list of actions triggered by a button or other control. Use it when a set of related actions does not need to be visible at all times.
Use fd-menu and fd-menu-item together to create an action menu that follows the WAI-ARIA menu-button pattern. The menu renders a role="menu" container inside a native popover="auto" surface, with no legacy non-popover fallback path in production. Each item renders a native <button role="menuitem">.
When to use
- A group of related actions shares one trigger — "Save as draft," "Save & submit," and "Discard" are logically grouped and do not all need to be visible at the same time.
- Screen space is constrained — A toolbar or table row has room for one action button but needs to offer secondary actions on demand.
- The actions are infrequent — Users do not need to see every option at a glance. Hiding low-frequency actions behind a trigger reduces visual noise.
When not to use
- Don't use a menu for navigation links —
fd-menuusesrole="menu"androle="menuitem", which signal actions to assistive technology. For navigation, use a<nav>with regular links. - Don't use a menu for form controls — Selection from a list of options is a listbox or select pattern, not a menu. Menus are for actions that happen when activated, not for choosing a value.
- Don't use a menu for a single action — If there is only one action, use a button directly. Menus add interaction cost.
- Don't nest menus (submenus) — Submenus are not supported in v1 and add significant accessibility and usability complexity. Flatten the action list or use a different pattern.
Examples
The second embed is intentional. The long-menu state demonstrates internal scrolling behavior that the overview story cannot communicate clearly in a single compact preview.
- Label the trigger with what the menu contains so the action list is predictable before opening.
- Keep destructive actions last and visually distinct.
- Leave disabled actions visible when discoverability matters, but avoid filling a menu with mostly unavailable items.
Properties
| Name | Type | Default | Description |
|---|---|---|---|
anchor | string | undefined | undefined | ID of the external trigger element that owns aria-expanded and positioning |
placement | Placement | bottom-start | Preferred popup placement relative to the anchor element |
open | boolean | false | Current open state |
label | string | undefined | undefined | Accessible name for the menu via aria-label |
labelledby | string | undefined | undefined | Accessible name source for the menu via aria-labelledby |
Slots
| Name | Description |
|---|---|
| (default) | One or more fd-menu-item children |
Events
| Name | Detail | Description |
|---|---|---|
fd-menu-open-change | { open: boolean } | Fired whenever the menu opens or closes |
Compatibility note:
fd-menustill fires deprecatedfd-openduring the compatibility window.- New consumer code should listen to
fd-menu-open-change.
CSS custom properties
| Name | Default | Description |
|---|---|---|
--fd-menu-border-radius | var(--fdic-corner-radius-lg, 7px) | Menu surface corner radius |
--fd-menu-min-width | 180px | Minimum menu width |
--fd-menu-max-width | 320px | Maximum menu width |
--fd-menu-max-height | 300px | Maximum menu height before internal scrolling |
Shadow parts
| Name | Description |
|---|---|
surface | Popover surface element |
menu | Internal element with role="menu" |
Methods
| Name | Description |
|---|---|
show() | Opens the menu, positions it, focuses the first item, and fires fd-menu-open-change |
showLast() | Opens the menu and focuses the last item. Use for ArrowUp-to-open behavior. |
hide() | Closes the menu and fires fd-menu-open-change |
toggle() | Opens or closes the menu based on the current open state |
Best practices
Label the trigger with what the menu contains
"Filing actions" or "Export options" tells the user what to expect before opening the menu.
Use vague triggers like "More" or "..."
Generic triggers force the user to open the menu to understand what it contains. In regulatory contexts, predictability builds trust.
Put destructive actions last
Placing destructive actions at the end of the menu reduces accidental activation and follows user expectations.
Mix destructive and non-destructive actions randomly
Interleaving high-risk and low-risk actions increases the chance of mistakes in time-pressured workflows.
Content guidelines
Menu items are actions. Lead with what happens when the user activates the item.
Export as PDF
PDF export
Menu items should be scannable. Move additional context to surrounding UI.
Discard filing
Discard this filing and all associated data permanently
Accessibility
fd-menurendersrole="menu"inside a nativepopover="auto"surface. The menu container requires an accessible name — setlabel(foraria-label) orlabelledby(foraria-labelledby) onfd-menu.Popover is the production model: outside click and browser-managed top-layer behavior come from the Popover API. The component still owns placement math, keyboard behavior, and trigger
aria-expanded.fd-menu-itemrenders a native<button role="menuitem">inside shadow DOM. The button text provides the accessible name.Keyboard model follows the WAI-ARIA menu-button pattern:
Key Behavior ArrowDown Move to next item (wraps to first) ArrowUp Move to previous item (wraps to last) Home Move to first item End Move to last item Enter / Space Activate item, close menu, return focus to trigger Escape Close menu, return focus to trigger Tab Close menu, allow natural focus movement Roving tabindex: Only one item has
tabindex="0"at a time; the rest havetabindex="-1". Arrow keys move focus between items.Disabled items remain in the arrow-key rotation so users can discover them, but Enter/Space on a disabled item is a no-op. Disabled items use
aria-disabled="true".aria-expanded: Whenanchoris set onfd-menu, the component managesaria-expandedon the anchor element automatically. The consumer must setaria-haspopup="menu"on the trigger.Focus return: On close via Escape or item activation, focus returns to the trigger. On close via outside click, focus goes to the click target. On close via Tab, focus moves naturally.
Forced colors: Menu surface and items use system colors (
ButtonBorder,ButtonText,Highlight,HighlightText,GrayText) so the menu remains distinguishable in Windows High Contrast mode.Reduced motion: A media query guard suppresses any future animations under
prefers-reduced-motion: reduce.
fd-menu-item contract
fd-menu-item is a supporting embedded primitive. It does not get its own top-level docs page, so its authoring contract lives here.
Purpose and relationship to parent
- Use
fd-menu-itemonly as a child action primitive insidefd-menuor composed components that adoptfd-menu-iteminto an internal menu, such asfd-split-button. - It represents one actionable row in a menu. It is not a navigation link, option, checkbox item, or radio item in v1.
Supported authored surface
| Name | Type | Default | Notes |
|---|---|---|---|
variant | "default" | "destructive" | "default" | Use destructive only for high-risk actions |
disabled | boolean | false | Keeps the item discoverable while suppressing activation |
| default slot | text | — | Visible item label |
icon-start slot | fd-icon or equivalent icon content | — | Optional leading icon |
Authoring constraints
- Author only short action labels. Start with a verb.
- Keep destructive items last in the parent menu and mark them with
variant="destructive". - Do not use
fd-menu-itemoutside a menu context or as a standalone button substitute. - Do not treat it as navigation content. Use link patterns for navigation.
Accessibility contract
fd-menu-itemrenders a native<button role="menuitem">inside shadow DOM.- Keyboard movement between items is owned by the parent
fd-menu. - Disabled items remain discoverable in menu navigation and expose
aria-disabled="true". - Activation fires
fd-menu-item-selectfor new code and deprecatedfd-selectduring the compatibility window.
Compatibility note:
fd-menu-itemstill fires deprecatedfd-selectduring the compatibility window.- New consumer code should listen to
fd-menu-item-select.
Usage example
<fd-menu label="Account actions" anchor="account-actions">
<fd-menu-item>Edit profile</fd-menu-item>
<fd-menu-item disabled>Publish filing</fd-menu-item>
<fd-menu-item variant="destructive">Delete draft</fd-menu-item>
</fd-menu>Trigger requirements
The trigger element (the button that opens the menu) must have:
aria-haspopup="menu"— set by the consumeraria-expanded— managed automatically byfd-menuwhenanchoris set- Keyboard handling to open the menu (Enter/Space/ArrowDown for first item, ArrowUp for last item) — consumer's responsibility for standalone usage; composed components like
fd-split-buttonhandle this internally
Known limitations
- Standalone usage is advanced —
fd-menudoes not render or manage its trigger. Standalone consumers must wirearia-haspopup, trigger keyboard behavior, andshow()/hide()calls manually. The recommended path is composed components likefd-split-button, which handle all wiring internally. - No type-ahead — Character search to jump to matching items is deferred from v1.
- No submenus — Nested/cascading menus are out of scope.
- No separators or groups — Menu item separators and named groups are deferred.
- No checkbox or radio items —
menuitemcheckboxandmenuitemradioroles are out of scope. - No link items —
fd-menu-itemrenders an action button, not a navigation link. Navigation-link menus are a separate future primitive. - No animation — Open/close transitions are not implemented in v1.