abaabil

Menubar

27th lightest of the forty, by js weight

The W3C APG menubar pattern: File, Edit, View across the top. It is a container for your own Menu elements, and that is the decision that keeps it small.

Example (a11y tier)

Tab into it once, then Left and Right move between the menus. ArrowDown opens the focused one; with a menu open, Left and Right sweep across the bar opening each neighbour in turn, and Escape closes.

Import

import Menubar from 'abaabil/menubar'         // structure only
import Menubar from 'abaabil/menubar/styled'  // + CSS
import Menubar from 'abaabil/menubar/a11y'    // + role, roving tabindex, Left and Right

A container, not a second menu

A menu bar in other libraries is a second implementation of the menu: its own trigger, its own panel, its own item roles and keyboard. This one takes your Menu elements as children, the same way Toolbar takes arbitrary controls. Each menu already has aria-haspopup, a live aria-expanded, role="menu" on the panel, Up and Down inside it, and Escape and light dismiss from the Popover API. None of that is written twice.

What a bar adds over a row of menus is only the sideways axis: role="menubar", role="menuitem" on each trigger, one tab stop for the whole row, Left and Right with wrapping, Home and End, and Down to open the focused menu. While a menu is open, Left and Right close it and open its neighbour.

The bar only claims what the menu has not

A key pressed inside an open panel bubbles up to the bar as well. The bar checks defaultPrevented and leaves anything the menu already handled alone, which is how Home and End mean “first and last item” while a menu is open and “first and last menu” while none is. Escape, Up and Down and typeahead inside a panel stay the menu's.

Coupled by a class name, on purpose

The bar finds its triggers with one selector, .abaabil-menu__trigger, and reads each menu's own aria-expanded to know which one is open. That is a real coupling to the Menu component, and it is read from the DOM rather than imported so that this entry point does not pull a second copy of the menu's code and stylesheet into the bundle. Use the a11y tier of Menu inside the a11y tier of Menubar; a trigger without that class is not part of the bar.

The stylesheet crosses the same line: it makes each trigger's border transparent, since a row of boxed buttons reads as a toolbar, and tints the open one so which menu is open is visible without hover.

One APG key is skipped: ArrowUp opening a menu on its last item. Down opens on the first, and the menu's own Up wraps to the end from there.

Props

PropTypeDefaultTierDescription
classNamestring—allMerged with the base class.
labelstring—a11yAccessible name. An unnamed menubar is announced as “menu bar” and nothing else.