Skip to main content

rc-menu

Menu popup for command surfaces with keyboard navigation and typed activation events, following the WAI-ARIA Menu pattern.

Package
@rcarls/rc-menu
Element
<rc-menu>
Native dependency
Consumer supplies menu item controls
State model
Host focus with an active descendant
Main events
rc-menu-activaterc-menu-close

Installation​

npm install @rcarls/rc-webcomponents@next
import '@rcarls/rc-webcomponents/rc-menu/define';

Usage​

Place focusable elements, usually native buttons, as the menu items, and name the menu with label. Elements that cannot take focus, such as separators, render but are skipped during keyboard navigation. A menu usually sits inside an rc-menu-button.

<rc-menu label="File">
<button type="button" value="new">New</button>
<button type="button" value="open">Open…</button>
<hr />
<button type="button" value="save-as">Save As…</button>
</rc-menu>

Live demo​

Accessibility​

rc-menu is the focus target and owns the menu role. It exposes the active slotted item through aria-activedescendant instead of moving DOM focus between items. Arrow Down and Arrow Up move the virtual cursor and wrap at the menu boundaries; Home and End select the first or last item. Enter, Space, and pointer interactions activate menu items, while Escape requests that the containing popup close. See the WAI-ARIA Menu pattern.

The public focusFirst(), focusLast(), focusItem(), and focusItemAt() methods follow the same model: each focuses the host and updates the virtual cursor. The read-only items getter returns the current navigable elements in document order.

Direct focusable children become menuitem entries. Use role="menuitemcheckbox" or role="menuitemradio" with aria-checked for checked choices; activation updates the checked state before the activation event is dispatched. A labeled role="group" can contain one level of related items, and <hr> or role="separator" elements divide sections without joining keyboard navigation.

<rc-menu label="View">
<button type="button" role="menuitemcheckbox" aria-checked="true" value="details">
Show details
</button>
<hr />
<button type="button" value="duplicate">
<span>Duplicate</span>
<kbd data-menu-shortcut>Ctrl+D</kbd>
</button>
</rc-menu>

Nested menu triggers supply their own visual affordance through rc-menu-button's indicator slot. rc-menu does not generate an indicator, leaving iconography and writing-direction behavior to the application or theme.

Events​

Both events bubble across shadow boundaries and are not cancelable.

EventDetailWhen
rc-menu-activate{ item, value, text, checked? }Enter, Space, or a pointer click activates an enabled item
rc-menu-close{ reason: 'escape' }Escape requests that the containing popup close

The activation value comes from data-value or value, text is the item's trimmed text content, and checked reports the resulting checkbox or radio state when applicable.

Theming​

The default demo mode shows the component without a package theme. Use the shared preview controls on this page to compare inherited, light, and dark color schemes or to apply the optional Material theme only inside the demo frames.

Slotted rows remain in light DOM. rc-menu injects their structural base styles once per containing document or shadow root under @layer rc-base, so consumer styles outside that layer can override them. Inherited --rc-menu-* custom properties customize the host and rows; the component does not expose CSS parts. Add trailing keyboard hints with [data-menu-shortcut].

API​

Properties​

PropertyMarkupTypeDefaultDescription
labellabelstring''Accessible label for this menu. Synced to `aria-label` on the host. Prefer `aria-labelledby` for a visible label associated via ID.
itemsJS property onlyreadonly Element[]Not specifiedAll navigable menu item elements in document order.

Methods​

MethodDescription
focusFirst()Move the virtual cursor and DOM focus to the first navigable item.
focusLast()Move the virtual cursor and DOM focus to the last navigable item.
focusItem($item?: Element | null)Move the virtual cursor to a specific item.
focusItemAt(index: number)Move the virtual cursor to the item at `index`.

Events​

EventDetail typeDescription
rc-menu-activateNo detail type documentedFired when a menu item is activated via keyboard (Enter/Space) or pointer click.
rc-menu-closeNo detail type documentedFired when Escape is pressed.

Slots​

NameDescription
defaultMenu items, groups, and separators. Supported content model: - Focusable elements (`<button>`, `<a>`, `[tabindex]`) become navigable `role="menuitem"` entries. - `role="menuitemcheckbox"` / `role="menuitemradio"` elements get a trailing indicator column via `::after` (coexists with a leading icon the item supplies itself); `aria-checked` is initialized when missing and updated on activation. - `role="group"` divs group related items; label them with `aria-label` or `aria-labelledby`. Optionally add a visible `[data-group-label]` element as first child of the group for section headings. - `role="separator"` / `<hr>` produce horizontal dividers between sections. - Within any item, use `[data-rc-menu-leading]`, `[data-rc-menu-label]`, and `[data-rc-menu-trailing]` to identify content columns. `[data-rc-menu-shortcut]` (and the legacy `[data-menu-shortcut]`) is pushed to the inline-end edge. - Nested menu triggers supply their own trailing indicator through `rc-menu-button`'s `indicator` slot.

CSS Custom Properties​

PropertyDefaultDescription
--rc-menu-min-width10emMinimum width of the menu panel.
--rc-menu-padding-blockvar(--rc-popup-padding-block)Block (top/bottom) padding inside the panel.
--rc-menu-backgroundvar(--rc-popup-background)Background color.
--rc-menu-bordervar(--rc-popup-border)Border.
--rc-menu-radiusvar(--rc-popup-radius)Menu panel border radius.
--rc-menu-shadowvar(--rc-popup-shadow)Box shadow.
--rc-menu-colorvar(--rc-popup-color)Text color.
--rc-menu-max-inline-sizecalc(100dvi - 0.5rem)Viewport-aware maximum inline size.
--rc-menu-max-block-sizecalc(100dvb - 0.5rem)Viewport-aware maximum block size; taller menus scroll.
--rc-menu-item-min-block-size0Minimum block size for menu item rows.
--rc-menu-item-padding-blockvar(--rc-item-padding-block)Menu item block-axis padding.
--rc-menu-item-padding-inlinevar(--rc-item-padding-inline)Menu item inline-axis padding.
--rc-menu-item-gapvar(--rc-item-gap)Gap between flex children inside each item.
--rc-menu-item-transitionNot specifiedCSS transition applied to each item row.
--rc-menu-hover-bgcolor-mix(in srgb, Highlight 8%, transparent)Pointer-hover background.
--rc-menu-hover-colorinheritPointer-hover text color.
--rc-menu-active-bgcolor-mix(in srgb, Highlight 8%, transparent)Virtual-cursor active background.
--rc-menu-active-colorinheritVirtual-cursor active text color.
--rc-menu-check-size1.25emWidth of the trailing indicator column for checkbox/radio items.
--rc-menu-check-colorinheritColor of the check/radio symbol.
--rc-menu-shortcut-size0.8emFont size of `[data-rc-menu-shortcut]` labels.
--rc-menu-shortcut-colorGrayTextText color of `[data-rc-menu-shortcut]` labels.
--rc-menu-disabled-colorGrayTextDisabled menu item text color.
--rc-menu-disabled-opacityvar(--rc-disabled-opacity)Disabled menu item opacity.
--rc-menu-separator-border1px solid ButtonBorderSeparator border.
--rc-menu-separator-margin-blockvar(--rc-control-gap)Separator block-axis margin.
--rc-menu-separator-margin-inline0pxSeparator inline margin; set to match item padding for inset separators.
--rc-menu-group-label-padding-block0.1emBlock padding on `[data-group-label]` section headings.
--rc-menu-group-label-colorGrayTextText color of `[data-group-label]` section headings.
--rc-item-font-familyvar(--rc-font-family)Item font family; shared with listbox and adaptive-menu items.
--rc-item-font-sizevar(--rc-font-size)Item font size; shared with listbox and adaptive-menu items.
--rc-item-font-weightinheritItem font weight; shared with listbox and adaptive-menu items.
--rc-item-line-heightvar(--rc-line-height)Item line height; shared with listbox and adaptive-menu items.
--rc-item-letter-spacinginheritItem letter spacing; shared with listbox and adaptive-menu items.
--rc-item-icon-sizeinheritSize of icons marked with `data-rc-icon`, `data-rc-menu-leading`, or `data-rc-menu-icon`.