Shadix.Components.Menubar (shadix v0.0.1)

Copy Markdown View Source

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/ArrowRight move 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/End move between the open menu's items;
  • Escape closes 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, MenubarGroup are 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.

Functions

hide_menu(id)

Returns the Phoenix.LiveView.JS command that closes the menu with id.

Hides the content panel with a leave transition. Used by the hook's data-on-close (Escape / outside click / switching menus) and by menu items on select.

show_menu(id)

Returns the Phoenix.LiveView.JS command that opens the menu with id.

Shows the content panel with an enter transition. Used by the hook's data-on-open when switching the open menu via arrow keys or hover.

toggle_menu(id)

Returns the Phoenix.LiveView.JS command that toggles the menu with id.

Toggles the content panel's visibility with enter/leave transitions. The ShadixMenubar hook reacts to the visibility change to position the panel and switch the bar's open menu.