## menubar (`poetry_menubar`)

A horizontal bar of menus, like a desktop application menu.

Class: Poetry::Ui::Menubar::Component - BEM block `poetry-ui-menubar`.
Slot REQUIRED: with_menu (at least one menu) - a call without it raises.
- `dir:` (symbol) - one of ltr|rtl - The reading direction; :rtl flips arrow-key movement and submenu sides.
- `label:` (string) - required - The bar's accessible name - a page may hold more than one menubar.
- `loop:` (boolean) - default false - Wraps arrow-key movement past either end of the bar.
- `value:` (string) - Server-renders the menu with this value open (values default to "menu-<position>").
Slots: menus (The top-level menus. Each takes with_trigger (the menu button) plus the family item slots (with_item, with_checkbox_item, with_radio_group, with_sub, with_separator, ...); value: defaults to the menu's position.; many; each with_menu REQUIRES with_trigger inside its block (the top-level menu button); each with_menu REQUIRES with_item inside its block (at least one item)).
- PART `menubar` - The role=menubar bar - one horizontal roving tab stop across the triggers | states: data-open (some menu is open (value present; the coordinator flips the pair)); data-closed (no menu is open)
- PART `menubar-menu` - One logical menu - a display:contents wrapper hosting the trigger + content pair's menu and popper controllers
- PART `menubar-trigger` - The top-level menu button - a role=menuitem INSIDE the bar | states: data-value (the menu's value - the coordinator's open/close key); data-popup-open (its menu is open (written with aria-expanded; absence is the closed state)); data-disabled (trigger is disabled (written together with the disabled property))
- PART `menubar-content` - The role=menu popup panel - positioning, animation, and the open state ride here | states: data-open (menu is open (presence flips the pair at runtime)); data-closed (menu is closed or animating out (the server-rendered state)); data-side=top|right|bottom|left (the placement side (bottom initially; popper re-writes it after collision flips)); data-align=start|center|end (the alignment against the trigger (start initially; popper re-resolves it)) | vars: --transform-origin (popper's anchor-facing animation origin); --available-width (popper: viewport space left for the panel (post-flip)); --available-height (popper: viewport space left for the panel (post-flip)); --anchor-width (popper: the trigger's measured width); --anchor-height (popper: the trigger's measured height)
- PART `menubar-group` - role=group semantic grouping between separators
- PART `menubar-label` - Non-interactive heading for a run of items | states: data-inset (indented to align with checkbox/radio item text (inset: true))
- PART `menubar-item` - One role=menuitem action row | states: data-variant (default or destructive (the danger treatment)); data-inset (indented to align with checkbox/radio item text (inset: true)); data-disabled (item is disabled (always written together with aria-disabled))
- PART `menubar-checkbox-item` - A role=menuitemcheckbox toggle row | states: data-checked (checked (the controller re-writes the pair with aria-checked on activation)); data-unchecked (unchecked); data-disabled (item is disabled (always written together with aria-disabled)); data-close-on-select (per-item override of the menu's close-on-select default ("false" keeps the menu open))
- PART `menubar-radio-group` - role=group scoping one single-select value | states: data-value (the selected radio value (the controller re-writes it on change))
- PART `menubar-radio-item` - A role=menuitemradio row inside a radio group | states: data-checked (the selected radio (the controller re-writes the pair with aria-checked)); data-unchecked (not selected); data-value (the radio's value); data-disabled (item is disabled (always written together with aria-disabled))
- PART `menubar-checkbox-item-indicator` - The check glyph slot inside checkbox items - aria-hidden; the item's aria-checked/data-checked pair carries state
- PART `menubar-radio-item-indicator` - The circle glyph slot inside radio items - aria-hidden; the item's aria-checked/data-checked pair carries state
- PART `menubar-separator` - role=separator rule between groups
- PART `menubar-shortcut` - The trailing keybinding HINT - aria-hidden, never binds the key
- PART `menubar-sub` - A submenu scope - hosts its own popper around the sub trigger/content pair
- PART `menubar-sub-trigger` - The role=menuitem row opening its submenu | states: data-popup-open (its submenu is open (written with aria-expanded; absence is the closed state)); data-inset (indented to align with checkbox/radio item text (inset: true))
- PART `menubar-sub-content` - The nested role=menu panel - its own popper content on the same presence machinery | states: data-open (submenu is open (presence flips the pair at runtime)); data-closed (submenu is closed (the server-rendered state)); data-side=top|right|bottom|left (the placement side (right/left by direction; popper resolves it at runtime)); data-align=start|center|end (the alignment against the sub-trigger (popper resolves it at runtime)) | vars: --transform-origin (popper's anchor-facing animation origin); --available-width (popper: viewport space left for the panel (post-flip)); --available-height (popper: viewport space left for the panel (post-flip)); --anchor-width (popper: the sub-trigger's measured width); --anchor-height (popper: the sub-trigger's measured height)
- WIRING root: `poetry--core--menubar` registers; values value, loop; actions slideAdjacent on poetry:menu:edge-navigate, onMenuClosed on poetry:menu:closed | `poetry--core--roving-focus` registers; values orientation, manage_tabindex, loop; actions keydown on keydown
- WIRING menu_wrapper: `poetry--core--menu` registers; values open, modal | `poetry--core--popper` registers; values side, align, side_offset, align_offset, avoid_collisions
- WIRING trigger: `poetry--core--menubar` actions toggle on pointerdown, hoverSlide on pointerenter, triggerKeydown on keydown | `poetry--core--popper` targets anchor
- WIRING content: `poetry--core--popper` targets content
- WIRING item: `poetry--core--menu` actions activate on click
- WIRING sub_trigger: `poetry--core--menu` actions subEnter on pointerenter, subLeave on pointerleave, openSub on click | `poetry--core--popper` targets anchor
- RULE: Use poetry_menubar for app-chrome command menus ONLY - site navigation is NavigationMenu (untrapped), a single actions menu is DropdownMenu.
- RULE: label: is REQUIRED (the bar's accessible name).
- RULE: Never put non-menuitem interactive elements directly in the bar (breaks roving focus + APG roles) - a Toolbar is the component for mixed controls.
- RULE: shortcut: is a visual hint ONLY - it does not register a keybinding; wire real shortcuts separately.
- RULE: Do not hand-wire hover-open-from-cold; hover only slides between menus once one is open (the gated-hover rule).
- RULE: In-menu item rules (destructive variant, inset, checkbox/radio) follow the DropdownMenu family contract.
