Photon Design System

Menubar

A horizontal strip of top-level menus — the desktop-app File / Edit / View bar. Built on Base UI Menubar: place Menu components inside and the bar coordinates roving focus across them, and once one menu is open, moving the pointer to a sibling trigger switches to it without a click.

Import

import { Menubar } from "@photon-ai/pho-ui/components/menubar";
import { Menu } from "@photon-ai/pho-ui/components/menu";

Basic

Each top-level menu is a Menu whose Menu.Trigger is styled as a menubar button. The rest of the menu — Portal, Positioner, Popup, and Items — is exactly the Menu composition.

<Menubar>
  <Menu.Root>
    <Menu.Trigger className={triggerClass}>File</Menu.Trigger>
    <Menu.Portal>
      <Menu.Positioner align="start" sideOffset={8}>
        <Menu.Popup>
          <Menu.Item>New File</Menu.Item>
          <Menu.Item>Open…</Menu.Item>
        </Menu.Popup>
      </Menu.Positioner>
    </Menu.Portal>
  </Menu.Root>
  {/* …Edit, View */}
</Menubar>

Anatomy

  • Menubar — the role="menubar" container; coordinates roving focus across the top-level menus.
  • Menu.Root — one per top-level menu; owns that menu’s open state.
  • Menu.Trigger — the styled menubar button that opens its menu.
  • Menu.Portal → Positioner → Popup — the floating panel for that menu.
  • Menu.Item / Separator / Group — the actions inside, shared with Menu.

Props

Menubar forwards every Base UI Menubar prop:

  • orientation — horizontal · vertical (default horizontal) — the arrow-key axis and layout
  • loopFocus — boolean (default true) — wrap arrow-key focus back to the first menu at the ends
  • modal — boolean (default true) — lock scroll and block outside interaction while a menu is open
  • disabled — boolean (default false) — disable the whole bar
  • className — string — class applied to the bar
  • render — Base UI render prop to swap the underlying element
  • …native <div> attributes

Accessibility

  • Semantics — the bar renders role="menubar"; each Menu.Trigger is a menuitem that owns its menu popup. Only one trigger sits in the tab order at a time (roving tabindex), so Tab enters and leaves the whole bar as a single stop.
  • Focus — opening a menu moves focus into its popup; closing returns focus to the trigger it came from.
  • Pointer — once any menu is open, hovering a sibling trigger switches to it without a click.

Keyboard:

  • Left / Right — move between top-level menu triggers.
  • Down (or Enter / Space) — open the focused menu and move into its items.
  • Up / Down — move between items in the open menu.
  • Escape — close the open menu back to its trigger.
  • Home / End — jump to the first / last item in the open menu.
  • Typeahead — type an item’s label to jump to it.

Best practices

  • Use a menubar for dense, application-style UIs (editors, dashboards) — not for ordinary website navigation, where a NavigationMenu fits better.
  • Keep top-level labels short and conventional (File, Edit, View) so users can predict where actions live.
  • Group related actions within each menu and use Menu.Separator rather than one long flat list.