Skip to content

Menubar

A desktop-app-style top menu bar (File / Edit / View). Click or hover expands submenus (cascading popups), with arrow key support, Alt access keys and a focus trap.

Multi-group radio (independent checkmarks per group)

The value of a type: "group" item acts as a group id. Leaves inside the same group record their selection independently; when value is a JSON object string ({"group-id":"selected"}), groups don't interfere — both "Mode" and "Theme" can show a checkmark at once.

Multi-group radio

mode: preview, theme: dark

Action items (kind: "action")

Leaves with kind: "action" render as plain actions (menuitem): no checkmark, clicks do not write back value, and only oas-select is dispatched (detail.kind === "action"). Fits "Open / Save / About" style items.

Action items (kind: action)

value: mode (actions don't change it)

Shortcuts (shortcut)

The shortcut field (e.g. "Ctrl+N"): renders a key hint on the right, and auto-binds a document-level keydown — pressing the combo selects that item (preventDefault blocks the browser default).

Shortcuts

Try Ctrl+N / Ctrl+O / Ctrl+S

Basic usage

Basic usage

Nothing selected

Disabled items and groups

Submenus support disabled, type: "divider" separators and type: "group" group titles.

Disabled items and groups

Nothing selected

Controlled selection

The value attribute is controlled (it is in observedAttributes): an external setAttribute('value', ...) takes effect immediately and syncs the selected item (check/highlight) to the corresponding leaf item; internal clicks also write back to value (uncontrolled channel), and the host can listen to oas-select to take over.

Controlled selection (value attribute)

Select "New"Select "Undo"Clear selectionvalue: -

Checkbox items and keep-open (checkbox + close-on-select)

Leaves with kind: "checkbox" toggle a multi-select checked set (value is a JSON array); toggling a checkbox does not close the submenu (continuous toggling). close-on-select="false" keeps the submenu open even after radio/action selections.

Checkbox + close-on-select

Checked: ["grid"]

Controlled open (open)

The open attribute holds the value of the currently open top-level menu (open="" closes all). Controlled attribute: an external setAttribute('open', ...) opens/switches/closes immediately; internal changes write open back and dispatch oas-open-change (detail: { value, open }) for the host to take over.

Controlled open (open attribute)

Open "File"Open "Edit"Closeopen: -

Trigger mode and arrow-key wrap (trigger / loop)

trigger="click" (default): a top-level menu opens on click first; once one is open, hovering another top-level item switches to it (desktop convention). trigger="hover" opens directly on hover. loop="false" disables wrap-around at the edges.

Hover opens directly (trigger)

hover opens directly (no click-first)

No wrap-around (loop)

← stops at the first, → stops at the last

Disabled bar (disabled)

disabled disables the whole bar: top-level/sub-item clicks, keyboard navigation, shortcut hotkeys and Alt access keys are all blocked.

Disabled bar (disabled)

The whole bar is inert

side controls the first-level popup side (default bottom), align its alignment (default start), offset the gap to the trigger (px); show-arrow draws a visual arrow pointing at the trigger.

Popup positioning + arrow (side / align / offset / show-arrow)

side=top / align=end / offset=8 / show-arrow

Vertical orientation (orientation)

orientation="vertical": the bar stacks vertically, first-level popups default to the right; ↑/↓ move between top-level items, → opens a submenu.

Vertical (orientation)

Mobile hamburger folding (breakpoint)

breakpoint="600": when the viewport is ≤ 600px wide the bar folds into a hamburger button + popup menu (narrow-width folding); widen the window to restore the full bar.

Mobile hamburger (breakpoint)

Shrink the window (≤600px) to try the hamburger

Icons (icon)

Both top-level items and sub-items accept an icon field (icon-set name); icons follow the text color.

Icons (icon)

API

Attributes

AttributeDescriptionTypeDefault
alignFirst-level popup alignment: start (default) / center / end; with side top/bottom it aligns on the horizontal axis, with left/right on the vertical axisstring
breakpointMobile breakpoint (px, e.g. 600): when the viewport width is ≤ the breakpoint the bar collapses into a hamburger button + popup menu (narrow-width folding)string
close-on-selectWhether selecting a leaf closes the open submenu, default true (desktop menubar convention); close-on-select="false" keeps it open (multi-select scenario); kind:"checkbox" items never close on togglestring
disabledDisable the whole bar: top-level/sub-item clicks, keyboard navigation, shortcut hotkeys and Alt access keys are all blocked; visually desaturatedboolean
itemsTop-level menu items JSON (with submenu children)string[]
loopArrow-key wrap-around toggle, default true (loops at edges); explicit loop="false" stops at the edgesstring
offsetGap between the first-level popup and its trigger (px, default 4)string
openValue of the currently open top-level menu (open="" closes all). Controlled attribute (in observedAttributes): an external setAttribute('open', ...) opens/switches/closes immediately; internal click/hover/keyboard changes write it back and dispatch oas-open-change, letting the host take overstring
orientationArrangement direction: horizontal (default) / vertical (bar stacks vertically, first-level popups default to the right, arrow keys move top-level items up/down)
show-arrowShow a visual arrow on the popup pointing at the trigger
sideFirst-level popup side: bottom (default horizontal) / top / left / right (default vertical); cascading submenus are unaffectedstring
triggerTop-level menu trigger: click (default, click to open first, then hover switches — desktop convention) / hover (hover opens directly)
valueSelected value. As a plain string it is a single global selection (no-group scenarios, backward compatible); as a JSON object string (e.g. {"mode":"preview","theme":"dark"}) selections are recorded per group id — the value of a type:"group" item acts as the group id; as a JSON array string (e.g. ["grid","wrap"]) it is the checkbox checked-set (kind:"checkbox" items, multi-select)string

Events

EventDescription
oas-open-changeThe open top-level menu changed, detail: { value, open } (value = currently open top-level menu value, open = whether anything is open). Fired both on controlled setAttribute('open') and internal click/hover/keyboard changes (not on the first frame)
oas-selectAn item was selected, detail: { value, kind?, checked? }. kind only appears for action items (kind: "action"); checkbox items carry checked (new checked state); radio items omit detail.kind

Event detail note: the detail of oas-select is a component-internal object (value/kind) — not a native Event, so you can't preventDefault() on it or read a native event.target from it. To reach the native event, use the outer parameter of your listener (e.g. in addEventListener('oas-select', (e) => ...), e is a CustomEvent and e.detail is the component data).

MenubarItem fields (inherits MenuItem):

FieldDescriptionType
labelMenu textstring
valueSelection value (declared in the items JSON; after render the host tag carries a data-value lowercased attribute for internal lookup — hosts shouldn't rely on it as public API)string
kindLeaf semantics: radio (default, checkable, participates in value) / action (action item, no checkmark, doesn't write back value on click)string
shortcutShortcut hint (e.g. "Ctrl+N"); renders as a right-side kbd and auto-binds a document-level keydown (selects the item on match, preventDefault)string
accessKeyAlt access key (single character); defaults to the first ASCII letter of labelstring
disabledDisabledboolean
childrenSubmenu items (nested recursively, cascading to the right)MenubarItem[]

Keyboard: at top level / switch, /Enter opens the submenu, Esc closes; inside a submenu / move, enters a cascading submenu, returns to the parent; Home/End jump. Pressing Alt alone focuses the menu bar, Alt + access key opens the matching top-level menu. While a submenu is open, Tab cycles among its items (focus trap); roving tabindex keeps only the current top-level item tab-reachable.

Released under the MIT OR Apache-2.0 License.