A horizontal bar of menus, like a desktop application's menubar (File, Edit,
View, ...), built on client-side JS commands, Floating UI, and the
ShadixMenubar LiveView hook (assets/ts/menubar.ts).
Each menu is a trigger button (role="menuitem", aria-haspopup="menu")
paired with a Floating-UI-positioned content panel (role="menu"). The
trigger toggles its panel with toggle_menu/1 (enter/leave transitions); the
hook watches each panel's visibility with a MutationObserver, positions it
under its trigger with @floating-ui/dom (computePosition + autoUpdate,
bottom-start/flip/shift), and coordinates the bar as a whole.
Coordination handled by the hook:
- clicking a trigger opens that menu's content below it;
ArrowLeft/ArrowRightmove focus between menu triggers (roving), wrapping at the ends;- while any menu is open, focusing/hovering another trigger switches the open menu to it;
ArrowUp/ArrowDown/Home/Endmove between the open menu's items;Escapecloses the open menu and returns focus to its trigger;- a pointerdown outside the bar closes the open menu.
Simplifications for this v1 (noted per the brief):
- no submenus, checkbox/radio items, or item groups (shadcn's
MenubarSub*,MenubarCheckboxItem,MenubarRadioItem,MenubarGroupare not ported); - triggers do not auto-open on hover before the first click — a menu must be opened by click (or keyboard) first, after which hovering siblings switches between them, matching the shadcn "menubar feels open once you click" behaviour.
Each menu's trigger and content ids are derived from the required :id so
aria-controls, data-trigger, and the JS targets line up stably. All menus
within a bar should share a common id prefix (e.g. "app-menubar-file",
"app-menubar-edit") and the bar carries the phx-hook so it can find them.
Summary
Functions
Returns the Phoenix.LiveView.JS command that closes the menu with id.
Renders the horizontal menubar container.
A selectable menu item.
A non-interactive group label within a menu.
Renders a single menu within the bar: a trigger button plus its content panel.
A horizontal separator between menu sections.
A trailing keyboard-shortcut hint within a menu item.
Returns the Phoenix.LiveView.JS command that opens the menu with id.
Returns the Phoenix.LiveView.JS command that toggles the menu with id.