Skip to content
Home Theme Gallery

Menubar

The custom element is <hui-menubar>.

Overview

An application menu bar: one tab stop across a row of hui-dropdown-menu children, with left and right moving between menus while one is open.

Example

Two menus
Source
<hui-menubar label="Application">
<hui-dropdown-menu data-value="file">
<hui-button slot="trigger" variant="ghost" size="sm">File</hui-button>
<button role="menuitem" data-value="new">New</button>
<button role="menuitem" data-value="open">Open</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="edit">
<hui-button slot="trigger" variant="ghost" size="sm">Edit</hui-button>
<button role="menuitem" data-value="undo">Undo</button>
<button role="menuitem" data-value="redo">Redo</button>
</hui-dropdown-menu>
</hui-menubar>

The Go template that renders it:

<hui-menubar label="Application">
<hui-dropdown-menu data-value="file">
<button slot="trigger">File</button>
<button role="menuitem" data-value="new">New</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="edit">
<button slot="trigger">Edit</button>
<button role="menuitem" data-value="undo">Undo</button>
</hui-dropdown-menu>
</hui-menubar>

On a phone

Five short menus fit a 320px phone, and each opens on a tap inside the viewport. The bar does not fold: an application menubar is a desktop pattern, and more menus than fit are better served on a phone by one hui-dropdown-menu.

Five menus at a phone’s width 375 px wide
Source
<hui-menubar label="Application">
<hui-dropdown-menu data-value="file">
<hui-button slot="trigger" variant="ghost" size="sm">File</hui-button>
<button role="menuitem" data-value="first">First item</button>
<button role="menuitem" data-value="second">Second item</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="edit">
<hui-button slot="trigger" variant="ghost" size="sm">Edit</hui-button>
<button role="menuitem" data-value="first">First item</button>
<button role="menuitem" data-value="second">Second item</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="view">
<hui-button slot="trigger" variant="ghost" size="sm">View</hui-button>
<button role="menuitem" data-value="first">First item</button>
<button role="menuitem" data-value="second">Second item</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="profiles">
<hui-button slot="trigger" variant="ghost" size="sm">Profiles</hui-button>
<button role="menuitem" data-value="first">First item</button>
<button role="menuitem" data-value="second">Second item</button>
</hui-dropdown-menu>
<hui-dropdown-menu data-value="help">
<hui-button slot="trigger" variant="ghost" size="sm">Help</hui-button>
<button role="menuitem" data-value="first">First item</button>
<button role="menuitem" data-value="second">Second item</button>
</hui-dropdown-menu>
</hui-menubar>

API

Attributes2
Attributes
NameTypeDefaultDescription
opena <code>data-value</code>""Which menu is open. Reflected; the server may render one open.
labelstring"Application"The accessible name of the role="menubar".
Properties2
Properties
NameTypeDefaultDescription
openstring''Reflects to open.
labelstring"Application"Reflects to label.
Events2
Events
NameDescription
hui-openA menu opened. Detail: { value }.
hui-closeA menu closed. Detail: { value }.
Slots1
Slots
NameDescription
(default)One hui-dropdown-menu per menu, each with a data-value and a slotted [slot="trigger"].
::part() hooks1
::part() hooks
NameDescription
barThe role="menubar" element.

States

This element has no states beyond its default.

Server-side mechanics

The server owns the menus and their items, and may render one open with open. The element is not form-associated and submits nothing. Which menu is open is viewer-owned and announced with hui-open/hui-close. A swap that removes the bar closes its open menu with it, so nothing is left in the top layer.

Accessibility

  • The bar is a role="menubar" with a name; each trigger is a role="menuitem" with aria-haspopup and aria-expanded.
  • The bar is a single tab stop; arrow keys move between the menus.

Keyboard

Keyboard
KeysAction
Arrow Left/RightMoves between menus; with one open, opens the next without closing and reopening.
TabThe whole bar is one tab stop; the arrow keys move within it.
EscapeCloses the open menu and returns focus to its trigger.

Gotchas

  • Each child must be a hui-dropdown-menu with a data-value and a slotted [slot="trigger"]; the bar only owns the roving tab stop and the left/right movement.
  • A server-rendered open is applied after the slotted menus upgrade, so it is safe to render the bar already open.