Skip to main content

rc-adaptive-menu

Priority-aware action toolbar that preserves authored controls while moving lower-priority actions into an overflow menu.

Package
@rcarls/rc-adaptive-menu
Element
<rc-adaptive-menu>
Native dependency
Consumer supplies buttons, links, or supported rc wrappers
State model
Controlled or uncontrolled open state
Main events
rc-adaptive-menu-toggle

Installation​

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

Usage​

Place native buttons as direct children and name the menu with label. Higher data-priority values stay visible first, up to max-shown; the rest move to the overflow menu, as does any action with slot="overflow".

<rc-adaptive-menu label="Document actions" max-shown="3">
<button type="button" data-priority="30">
<span data-rc-menu-leading aria-hidden="true">★</span>
<span data-rc-menu-label>Favorite</span>
</button>
<button type="button" data-priority="20">
<span data-rc-menu-leading aria-hidden="true">✎</span>
<span data-rc-menu-label>Edit</span>
</button>
<button type="button" slot="overflow">
<span data-rc-menu-label>Delete</span>
</button>
</rc-adaptive-menu>

Live demo​

Change "Max shown" to see actions move between the toolbar and overflow menu. Clicking either presentation invokes the same authored control.

Action contract​

Actions must be direct native buttons or links, or direct rc-button, rc-chip, or rc-menu-button wrappers. Larger numeric data-priority values are promoted first, up to max-shown authored actions; DOM order breaks ties. An authored slot="overflow" keeps an action overflow-only, regardless of max-shown.

max-shown is a static declarative cap, re-evaluated whenever it or an authored action's data-priority changes. The component performs no runtime size measurement of any kind, so promoted actions are not guaranteed to visually fit any particular container. A consumer whose promoted count needs to react to available space, such as a responsive breakpoint or a window size class, owns that decision and writes the resulting max-shown value down.

The component preserves node identity. It re-slots the original action and temporarily owns its menu role and tabindex, restoring authored values when the action is promoted, removed, or the component disconnects. There are no generated action proxies.

Themes can align action contents with rc-menu through these shared markers:

  • data-rc-menu-leading
  • data-rc-menu-label
  • data-rc-menu-trailing
  • data-rc-menu-shortcut

Open state​

Use default-open to seed uncontrolled state. In controlled usage, write open and respond to rc-adaptive-menu-toggle; the event's detail.open contains the state requested by pointer or keyboard interaction. Host writes and calls to openMenu(), closeMenu(), or toggleMenu() are silent.

<rc-adaptive-menu id="actions" max-shown="2">
<button type="button">Edit</button>
<button type="button">Archive</button>
<button type="button">Delete</button>
</rc-adaptive-menu>

<script>
const menu = document.querySelector('#actions');

menu.addEventListener('rc-adaptive-menu-toggle', (event) => {
menu.open = event.detail.open;
});
</script>

The $actions, $promotedActions, and $overflowedActions getters return the current original elements in light-DOM order.

Accessibility​

The promoted controls follow the APG toolbar pattern, including orientation- aware and right-to-left arrow navigation. Overflowed controls use menu-item roles, vertical menu navigation, Escape dismissal, light dismissal, and focus return. Without the Popover API, the same interaction remains available through an explicitly positioned fallback popup.

The overflow trigger's own accessible touch target is conventionally the trailing-most control in a toolbar, so it commonly leaves dead space before the container's own edge padding. --rc-adaptive-menu-touch-target-overlap-inline-end (zero by default) lets a theme or consumer give that space back so the trigger sits flush with the edge instead, following the same pattern as rc-button's own touch-target overlap tokens.

Localization​

Built-in text follows the element's own lang, else <html lang>. Override it with messages, or register it for every instance under rc-adaptive-menu: label, overflow. See Localization.

API​

Properties​

PropertyMarkupTypeDefaultDescription
messagesJS property onlyPartial<RCAdaptiveMenuMessages> | undefinedNot specifiedBuilt-in text overrides; unset keys fall back to registered text, then English.
labellabelstring | undefinedNot specifiedAccessible label for the toolbar. Defaults to the `label` message.
maxShownmax-shownnumber3Maximum authored actions promoted ahead of the overflow trigger. A static declarative cap, re-evaluated whenever it changes — not a measurement of available space.
openopenbooleanNot specifiedWhether the overflow menu is visible. Host writes are silent.
defaultOpendefault-openbooleanNot specifiedInitial open state for uncontrolled usage.
orientationorientation'horizontal' | 'vertical''horizontal'Toolbar layout and arrow-key navigation axis.
$actionsJS property onlyHTMLElement[]Not specifiedOriginal authored action elements in DOM order.
$promotedActionsJS property onlyHTMLElement[]Not specifiedActions currently shown in the toolbar, in authored DOM order.
$overflowedActionsJS property onlyHTMLElement[]Not specifiedActions currently assigned to the overflow menu, in authored DOM order.

Methods​

MethodDescription
openMenu(focus: 'first' | 'last' | 'none')Opens the overflow popup silently and optionally focuses an edge action.
closeMenu(returnFocus: unknown)Closes the overflow popup silently.
toggleMenu(focus: 'first' | 'last' | 'none')Toggles the overflow popup silently.

Events​

EventDetail typeDescription
rc-adaptive-menu-toggleCustomEventFired when user interaction requests a change to `open`.

Slots​

NameDescription
defaultDirect native actions or supported rc action wrappers.
overflowOverflow-only actions and actions re-slotted by the component.
overflow-iconOptional decorative icon for the overflow trigger.

CSS Custom Properties​

PropertyDefaultDescription
--rc-adaptive-menu-gapvar(--rc-control-gap)Gap between promoted actions and the overflow trigger.
--rc-adaptive-menu-trigger-inline-size2.5emOverflow trigger minimum inline size.
--rc-adaptive-menu-trigger-block-size2.5emOverflow trigger minimum block size.
--rc-adaptive-menu-touch-target-inline-sizeNot specifiedMinimum overflow trigger activation-area inline size. Defers to `--rc-adaptive-menu-touch-target-block-size` when unset.
--rc-adaptive-menu-touch-target-block-size3remMinimum overflow trigger activation-area block size.
--rc-adaptive-menu-touch-target-overlap-inline-start0pxZero by default. A theme or consumer sets this when the overflow trigger sits at a real leading edge (no neighbor on that side) to let its touch-target inflation overlap into whatever sits just outside the host, such as a container's own edge padding, instead of also reserving layout space there.
--rc-adaptive-menu-touch-target-overlap-inline-end0pxThe trailing-edge counterpart to `--rc-adaptive-menu-touch-target-overlap-inline-start` — the overflow trigger is conventionally the trailing-most control in a toolbar, so this is the one commonly set.
--rc-adaptive-menu-trigger-padding0.5emOverflow trigger padding.
--rc-adaptive-menu-trigger-border1px solid ButtonBorderOverflow trigger border.
--rc-adaptive-menu-trigger-radiusvar(--rc-control-radius)Overflow trigger radius.
--rc-adaptive-menu-trigger-backgroundButtonFaceOverflow trigger background.
--rc-adaptive-menu-trigger-colorButtonTextOverflow trigger color.
--rc-adaptive-menu-trigger-hover-backgroundvar(--rc-adaptive-menu-trigger-background)Overflow trigger background under the pointer.
--rc-adaptive-menu-trigger-shadownoneOverflow trigger box shadow.
--rc-adaptive-menu-trigger-active-shadowvar(--rc-adaptive-menu-trigger-shadow)Overflow trigger box shadow while pressed.
--rc-item-font-familyinheritOverflow action label font family; shared with menu and listbox items.
--rc-item-font-sizeinheritOverflow action label font size; shared with menu and listbox items.
--rc-item-font-weightinheritOverflow action label font weight; shared with menu and listbox items.
--rc-item-line-heightinheritOverflow action label line height; shared with menu and listbox items.
--rc-item-letter-spacinginheritOverflow action label letter spacing; shared with menu and listbox items.
--rc-item-icon-sizeinheritOverflow action leading icon size; shared with menu items.
--rc-adaptive-menu-icon-size1.5emDefault overflow icon size.
--rc-adaptive-menu-popup-min-inline-size10emOverflow popup minimum inline size.
--rc-adaptive-menu-popup-max-inline-sizecalc(100dvi - 0.5rem)Overflow popup viewport-aware inline limit.
--rc-adaptive-menu-popup-max-block-sizecalc(100dvb - 0.5rem)Overflow popup viewport-aware block limit.
--rc-adaptive-menu-popup-padding-blockvar(--rc-popup-padding-block)Overflow popup block padding.
--rc-adaptive-menu-popup-bordervar(--rc-popup-border)Overflow popup border.
--rc-adaptive-menu-popup-radiusvar(--rc-popup-radius)Overflow popup radius.
--rc-adaptive-menu-popup-backgroundvar(--rc-popup-background)Overflow popup background.
--rc-adaptive-menu-popup-shadowvar(--rc-popup-shadow)Overflow popup shadow.
--rc-adaptive-menu-popup-colorvar(--rc-popup-color)Overflow popup foreground.
--rc-adaptive-menu-item-min-block-size2.5emOverflow action minimum block size.
--rc-adaptive-menu-item-padding-blockvar(--rc-item-padding-block)Overflow action block padding.
--rc-adaptive-menu-item-padding-inlinevar(--rc-item-padding-inline)Overflow action inline padding.
--rc-adaptive-menu-item-gapvar(--rc-item-gap)Overflow action content gap.

CSS Parts​

PartDescription
rootToolbar container.
overflow-triggerButton that opens the overflow menu.
popupOverflow menu popover.