# Menubar

URL: https://ark-ui.com/docs/react/components/menubar
LLM: https://ark-ui.com/llms.txt/components/menubar

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

---

---
id: menubar
title: Menubar
description: A horizontal bar of menus, like the menu bar of a desktop application.
status: new
---



## Anatomy

The menubar is a thin coordinator. It owns only a root element; the items it navigates are the triggers of the `Menu`
components rendered inside it.



```tsx
<Menubar.Root>
  <Menu.Root>
    <Menu.Trigger />
    <Portal>
      <Menu.Positioner>
        <Menu.Content>
          <Menu.Item />
        </Menu.Content>
      </Menu.Positioner>
    </Portal>
  </Menu.Root>
</Menubar.Root>
```

## Examples

### Basic

Each `Menu` inside a `Menubar.Root` becomes one of its items. The menubar takes over roving tabindex, arrow key
navigation, `Home`/`End`, and typeahead across the triggers, and the menus coordinate opening and closing between
themselves. No extra prop or wrapper is needed.

Once one menu is open, moving to a sibling with the arrow keys or the pointer switches to it directly.

```tsx
import { Menu } from '@ark-ui/react/menu'
import { Menubar } from '@ark-ui/react/menubar'
import { Portal } from '@ark-ui/react/portal'
import menu from 'styles/menu.module.css'
import styles from 'styles/menubar.module.css'

export const Basic = () => (
  <Menubar.Root className={styles.Root}>
    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>File</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="new">
              New File
            </Menu.Item>
            <Menu.Item className={menu.Item} value="open">
              Open...
            </Menu.Item>
            <Menu.Separator className={menu.Separator} />
            <Menu.Item className={menu.Item} value="save">
              Save
            </Menu.Item>
            <Menu.Item className={menu.Item} value="save-as">
              Save As...
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>Edit</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="undo">
              Undo
            </Menu.Item>
            <Menu.Item className={menu.Item} value="redo">
              Redo
            </Menu.Item>
            <Menu.Separator className={menu.Separator} />
            <Menu.Item className={menu.Item} value="cut">
              Cut
            </Menu.Item>
            <Menu.Item className={menu.Item} value="copy">
              Copy
            </Menu.Item>
            <Menu.Item className={menu.Item} value="paste">
              Paste
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger} disabled>
        Develop
      </Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="inspect">
              Inspect Element
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>View</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="zoom-in">
              Zoom In
            </Menu.Item>
            <Menu.Item className={menu.Item} value="zoom-out">
              Zoom Out
            </Menu.Item>
            <Menu.Item className={menu.Item} value="fullscreen">
              Toggle Fullscreen
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>
  </Menubar.Root>
)
```

### Nested Menus

Submenus work exactly as they do outside a menubar, with `Menu.TriggerItem`. `ArrowRight` on a submenu trigger opens the
submenu instead of moving to the next menu.

```tsx
import { Menu } from '@ark-ui/react/menu'
import { Menubar } from '@ark-ui/react/menubar'
import { Portal } from '@ark-ui/react/portal'
import menu from 'styles/menu.module.css'
import styles from 'styles/menubar.module.css'

export const Nested = () => (
  <Menubar.Root className={styles.Root}>
    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>File</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="new">
              New File
            </Menu.Item>
            <Menu.Item className={menu.Item} value="open">
              Open...
            </Menu.Item>
            <Menu.Separator className={menu.Separator} />
            <Menu.Root>
              <Menu.TriggerItem className={menu.TriggerItem}>Export</Menu.TriggerItem>
              <Portal>
                <Menu.Positioner>
                  <Menu.Content className={menu.Content}>
                    <Menu.Item className={menu.Item} value="pdf">
                      PDF
                    </Menu.Item>
                    <Menu.Item className={menu.Item} value="png">
                      PNG
                    </Menu.Item>
                    <Menu.Item className={menu.Item} value="svg">
                      SVG
                    </Menu.Item>
                  </Menu.Content>
                </Menu.Positioner>
              </Portal>
            </Menu.Root>
            <Menu.Separator className={menu.Separator} />
            <Menu.Item className={menu.Item} value="print">
              Print...
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>Edit</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="cut">
              Cut
            </Menu.Item>
            <Menu.Item className={menu.Item} value="copy">
              Copy
            </Menu.Item>
            <Menu.Item className={menu.Item} value="paste">
              Paste
            </Menu.Item>
            <Menu.Separator className={menu.Separator} />
            <Menu.Root>
              <Menu.TriggerItem className={menu.TriggerItem}>Find</Menu.TriggerItem>
              <Portal>
                <Menu.Positioner>
                  <Menu.Content className={menu.Content}>
                    <Menu.Item className={menu.Item} value="find">
                      Find...
                    </Menu.Item>
                    <Menu.Item className={menu.Item} value="find-next">
                      Find Next
                    </Menu.Item>
                    <Menu.Item className={menu.Item} value="replace">
                      Replace...
                    </Menu.Item>
                  </Menu.Content>
                </Menu.Positioner>
              </Portal>
            </Menu.Root>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>View</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="zoom-in">
              Zoom In
            </Menu.Item>
            <Menu.Item className={menu.Item} value="zoom-out">
              Zoom Out
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>
  </Menubar.Root>
)
```

### Vertical

Set `orientation="vertical"` to stack the triggers. Up and down then move between them, and `ArrowRight` opens the
focused menu as a fly-out.

```tsx
import { Menu } from '@ark-ui/react/menu'
import { Menubar } from '@ark-ui/react/menubar'
import { Portal } from '@ark-ui/react/portal'
import menu from 'styles/menu.module.css'
import styles from 'styles/menubar.module.css'

export const Vertical = () => (
  <Menubar.Root className={styles.Root} orientation="vertical">
    <Menu.Root positioning={{ placement: 'right-start' }}>
      <Menu.Trigger className={styles.Trigger}>Account</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="profile">
              Profile
            </Menu.Item>
            <Menu.Item className={menu.Item} value="billing">
              Billing
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root positioning={{ placement: 'right-start' }}>
      <Menu.Trigger className={styles.Trigger}>Workspace</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="members">
              Members
            </Menu.Item>
            <Menu.Item className={menu.Item} value="integrations">
              Integrations
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root positioning={{ placement: 'right-start' }}>
      <Menu.Trigger className={styles.Trigger}>Help</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="docs">
              Documentation
            </Menu.Item>
            <Menu.Item className={menu.Item} value="support">
              Contact Support
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>
  </Menubar.Root>
)
```

### Disabled

Set `disabled` on `Menubar.Root` to disable every trigger at once.

To disable a single menu instead, set `disabled` on its `Menu.Trigger`. It is skipped by keyboard navigation, never
becomes the tabbable item, and does not open on hover.

```tsx
import { Menu } from '@ark-ui/react/menu'
import { Menubar } from '@ark-ui/react/menubar'
import { Portal } from '@ark-ui/react/portal'
import menu from 'styles/menu.module.css'
import styles from 'styles/menubar.module.css'

export const Disabled = () => (
  <Menubar.Root className={styles.Root} disabled>
    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>File</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="new">
              New File
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>

    <Menu.Root>
      <Menu.Trigger className={styles.Trigger}>Edit</Menu.Trigger>
      <Portal>
        <Menu.Positioner>
          <Menu.Content className={menu.Content}>
            <Menu.Item className={menu.Item} value="undo">
              Undo
            </Menu.Item>
          </Menu.Content>
        </Menu.Positioner>
      </Portal>
    </Menu.Root>
  </Menubar.Root>
)
```

### Root Provider

Use the `useMenubar` hook with `Menubar.RootProvider` to read the menubar's state from outside the component.

```tsx
import { Menu } from '@ark-ui/react/menu'
import { Menubar, useMenubar } from '@ark-ui/react/menubar'
import { Portal } from '@ark-ui/react/portal'
import menu from 'styles/menu.module.css'
import styles from 'styles/menubar.module.css'

export const RootProvider = () => {
  const menubar = useMenubar()

  return (
    <div className="stack">
      <span>hasOpenMenu: {String(menubar.hasOpenMenu)}</span>
      <Menubar.RootProvider className={styles.Root} value={menubar}>
        <Menu.Root>
          <Menu.Trigger className={styles.Trigger}>File</Menu.Trigger>
          <Portal>
            <Menu.Positioner>
              <Menu.Content className={menu.Content}>
                <Menu.Item className={menu.Item} value="new">
                  New File
                </Menu.Item>
                <Menu.Item className={menu.Item} value="open">
                  Open...
                </Menu.Item>
              </Menu.Content>
            </Menu.Positioner>
          </Portal>
        </Menu.Root>

        <Menu.Root>
          <Menu.Trigger className={styles.Trigger}>Edit</Menu.Trigger>
          <Portal>
            <Menu.Positioner>
              <Menu.Content className={menu.Content}>
                <Menu.Item className={menu.Item} value="undo">
                  Undo
                </Menu.Item>
                <Menu.Item className={menu.Item} value="redo">
                  Redo
                </Menu.Item>
              </Menu.Content>
            </Menu.Positioner>
          </Portal>
        </Menu.Root>
      </Menubar.RootProvider>
    </div>
  )
}
```

## Guides

### Portal the menus

Menu content must be rendered in a `Portal`. The menubar treats every element with `role="menuitem"` inside its root as
one of its own items, so a `Menu.Positioner` left inline would have its menu items picked up as menubar triggers and
keyboard navigation would land on them.

```tsx
<Menu.Root>
  <Menu.Trigger>File</Menu.Trigger>
  {/* ✅ portalled out of the menubar root */}
  <Portal>
    <Menu.Positioner>
      <Menu.Content>{/* ... */}</Menu.Content>
    </Menu.Positioner>
  </Portal>
</Menu.Root>
```

### Skipping the animation between menus

Opening the first menu is a normal open and should animate. Moving from one menu to the next is a swap, and replaying
the enter and exit animations on every step reads as flicker.

Both the outgoing and the incoming content carry `data-instant` for that swap, so styles can opt out of the animation
without giving it up for the first open:

```css
[data-scope='menu'][data-part='content'][data-state='open'] {
  animation: fade-in 150ms ease-out;
}

[data-scope='menu'][data-part='content'][data-state='closed'] {
  animation: fade-out 100ms ease-in;
}

/* switching between menus in a menubar */
[data-scope='menu'][data-part='content'][data-instant] {
  animation: none;
}
```

`data-instant` is set when the swap comes from the arrow keys or from hovering a sibling trigger. Closing a menu on its
own, by clicking its trigger again or pressing `Escape`, clears it, so the next open animates normally.

## API Reference

### Props

### Root

#### Props

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`disabled`**
Type: `boolean`
Required: false
Default Value: `false`
Description: Whether the menubar (and all its menu triggers) is disabled.

**`ids`**
Type: `Partial<{ root: string }>`
Required: false
Default Value: `undefined`
Description: The ids of the elements in the menubar. Useful for composition.

**`loopFocus`**
Type: `boolean`
Required: false
Default Value: `true`
Description: Whether to loop the keyboard navigation across the triggers.

**`orientation`**
Type: `Orientation`
Required: false
Default Value: `"horizontal"`
Description: The orientation of the menubar.

**`render`**
Type: `ReactElement<unknown, string | JSXElementConstructor<any>> | RenderFn<EmptyState>`
Required: false
Default Value: `undefined`
Description: Render the part as a custom element, combining their props and behavior.

Pass an element to have the part's props merged into it, or a function to control the merge
yourself and read the part's state.

#### Data Attributes

**`data-menubar-root`**: <uid>
**`data-orientation`**: The orientation of the menubar
**`data-disabled`**: Present when disabled
**`data-has-open-menu`**: Present when a menu in the menubar is open

### RootProvider

#### Props

**`value`**
Type: `UseMenubarReturn`
Required: true
Default Value: `undefined`
Description: undefined

**`asChild`**
Type: `boolean`
Required: false
Default Value: `undefined`
Description: Use the provided child element as the default rendered element, combining their props and behavior.

**`render`**
Type: `ReactElement<unknown, string | JSXElementConstructor<any>> | RenderFn<EmptyState>`
Required: false
Default Value: `undefined`
Description: Render the part as a custom element, combining their props and behavior.

Pass an element to have the part's props merged into it, or a function to control the merge
yourself and read the part's state.

### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `hasOpenMenu` | `boolean` | Whether any menu within the menubar is open. |
| `orientation` | `Orientation` | The orientation of the menubar. |
| `disabled` | `boolean` | Whether the menubar is disabled. |
| `getMenuContext` | `() => MenubarMenuContext` | Returns the config to pass to each top-level menu's `menubar` prop. Adapters
usually expose this via a context so nested `<Menu>`s can read it. |


## Accessibility

Complies with the [Menubar WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/).

### Keyboard Support

**`ArrowRight + ArrowLeft`**
Description: In a horizontal menubar, moves focus to the next/previous menu. If a menu is open, opens the sibling menu.

**`ArrowDown + ArrowUp`**
Description: In a vertical menubar, moves focus to the next/previous menu. In a horizontal menubar, opens the focused menu.

**`Enter + Space`**
Description: Opens the focused menu and highlights its first item.

**`Home + End`**
Description: Moves focus to the first/last menu.

**`Esc`**
Description: Closes the open menu and returns focus to its trigger.
