# Menubar

> A persistent bar of menus for editor-style applications, as in File, Edit and View.

Category: Navigation · Status: stable · Package: @bindshq/stance-react@0.1.1 · Docs: https://stanceui.com/components/menubar

Use Menubar in dense, application-like tools such as a signature template editor, where users expect desktop-style menus. It implements the WAI-ARIA menubar pattern: one tab stop for the whole bar, arrow keys between menus, and ArrowLeft/ArrowRight to move between open menus. For website navigation use NavigationMenu instead.

## Import

```tsx
import { Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarItem, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubTrigger, MenubarSubContent } from '@bindshq/stance-react';
```

Styles are imported once per app: `@bindshq/stance-tokens/css` and `@bindshq/stance-react/styles.css`.

## Examples

### Template editor

```tsx
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from '@bindshq/stance-react';

export function Basic() {
  return (
    <Menubar aria-label="Template editor">
      <MenubarMenu>
        <MenubarTrigger>File</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            New template <MenubarShortcut>⌘N</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            Save <MenubarShortcut>⌘S</MenubarShortcut>
          </MenubarItem>
          <MenubarSub>
            <MenubarSubTrigger>Export</MenubarSubTrigger>
            <MenubarSubContent>
              <MenubarItem>HTML</MenubarItem>
              <MenubarItem>PNG image</MenubarItem>
            </MenubarSubContent>
          </MenubarSub>
          <MenubarSeparator />
          <MenubarItem>Close editor</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Edit</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>
            Undo <MenubarShortcut>⌘Z</MenubarShortcut>
          </MenubarItem>
          <MenubarItem>
            Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>
          </MenubarItem>
          <MenubarSeparator />
          <MenubarItem>Insert placeholder field</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
      <MenubarMenu>
        <MenubarTrigger>Insert</MenubarTrigger>
        <MenubarContent>
          <MenubarItem>Logo</MenubarItem>
          <MenubarItem>Social icons</MenubarItem>
          <MenubarItem>Promotional banner</MenubarItem>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  );
}
```

### Checkable items

```tsx
import * as React from 'react';
import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarTrigger } from '@bindshq/stance-react';

export function WithStateItems() {
  const [ruler, setRuler] = React.useState(true);
  const [device, setDevice] = React.useState('desktop');
  return (
    <Menubar aria-label="Preview">
      <MenubarMenu>
        <MenubarTrigger>View</MenubarTrigger>
        <MenubarContent>
          <MenubarCheckboxItem checked={ruler} onCheckedChange={setRuler}>
            Show ruler
          </MenubarCheckboxItem>
          <MenubarSeparator />
          <MenubarRadioGroup value={device} onValueChange={setDevice}>
            <MenubarRadioItem value="desktop">Desktop client</MenubarRadioItem>
            <MenubarRadioItem value="mobile">Mobile client</MenubarRadioItem>
            <MenubarRadioItem value="web">Outlook on the web</MenubarRadioItem>
          </MenubarRadioGroup>
        </MenubarContent>
      </MenubarMenu>
    </Menubar>
  );
}
```

### Controlled

Control which menu is open with value / onValueChange.

```tsx
import * as React from 'react';
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarTrigger } from '@bindshq/stance-react';

export function Controlled() {
  const [open, setOpen] = React.useState<string | null>(null);
  return (
    <div style={{ display: 'grid', gap: 12, justifyItems: 'start' }}>
      <Menubar aria-label="Document" value={open} onValueChange={setOpen}>
        <MenubarMenu value="document">
          <MenubarTrigger>Document</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Rename</MenubarItem>
            <MenubarItem>Version history</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu value="share">
          <MenubarTrigger>Share</MenubarTrigger>
          <MenubarContent>
            <MenubarItem>Invite collaborators</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
      </Menubar>
      <span style={{ color: 'var(--st-color-fg-muted)', fontSize: 'var(--st-font-size-sm)' }}>
        Open menu: {open ?? 'none'}
      </span>
    </div>
  );
}
```

## API reference

| Component | Prop | Type | Default | Description |
| --- | --- | --- | --- | --- |
| Menubar | `value / defaultValue` | `string \| null` | None | The open menu’s value (controlled or initial). |
| Menubar | `onValueChange` | `(value: string \| null) => void` | None | Called when a menu opens or closes. |
| Menubar | `loop` | `boolean` | `true` | Wrap focus between first and last menus. |
| Menubar | `aria-label` | `string` | None | Name of the menubar, e.g. “Template editor”. |
| MenubarMenu | `value` | `string` | None | Identifier for controlled usage. Generated by default. |
| MenubarTrigger | `...props` | `ButtonHTMLAttributes` | None | The top-level button (role menuitem). |
| MenubarContent | `align / sideOffset` | `Align / number` | `'start' / 6` | Placement of the menu under its trigger. |
| MenubarItem, MenubarCheckboxItem, MenubarRadioGroup, … | `None` | `None` | None | Identical to their DropdownMenu counterparts. |

## Accessibility

- The bar has role menubar and a single tab stop (roving tabindex) across its triggers.
- Triggers are menuitems with aria-haspopup, aria-expanded and aria-controls.
- With a menu open, ArrowLeft/ArrowRight close it and open the neighbouring menu with focus on its first item.
- Hovering across the bar while a menu is open switches menus, matching desktop conventions.

## Keyboard

| Keys | Action |
| --- | --- |
| `ArrowLeft` `ArrowRight` | Move between triggers, or between open menus. |
| `Home` `End` | First or last trigger. |
| `Enter` `Space` `ArrowDown` | Open the menu and focus its first item. |
| `ArrowUp` | Open the menu and focus its last item. |
| `Escape` | Close the menu and return focus to its trigger. |

## Guidelines

**Do**

- Reserve for application-like editors with many commands.
- Show keyboard shortcuts for frequent commands.

**Don’t**

- Use for marketing or documentation site navigation.

## Related

- https://stanceui.com/components/dropdown-menu
- https://stanceui.com/components/toolbar
- https://stanceui.com/components/navigation-menu
