Menubar
Menubar coordinates multiple Menu instances horizontally with shared open state and keyboard navigation between triggers.
Installation#
Usage#
Menubar wraps any number of Menu instances. Each Menu keeps its own popup, and the Menubar coordinates which one is open, focus path between triggers, and hover-to-switch between them.
import { Menubar, MenubarTrigger } from '@/components/ui/menubar';
import { Menu, MenuGroup, MenuItem, MenuList, MenuPopup, MenuPortal, MenuPositioner, MenuSeparator } from '@/components/ui/menu';<Menubar>
<Menu>
<MenubarTrigger>File</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup>
<MenuList>
<MenuGroup>
<MenuItem>New File</MenuItem>
<MenuItem>Open…</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>Save</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
<Menu>
<MenubarTrigger>Edit</MenubarTrigger>
{/* ... */}
</Menu>
</Menubar>MenubarTrigger is a styled wrapper around Menu.Trigger — use it for triggers that sit inside a Menubar so they pick up bar-level styling and data-open highlighting.
Examples#
Basic#
A standard application menubar with File, Edit, View, Help menus.
'use client';
import { Clipboard } from '@primeicons/react/clipboard';
import { Copy } from '@primeicons/react/copy';
import { Download } from '@primeicons/react/download';
import { File } from '@primeicons/react/file';
import { FolderOpen } from '@primeicons/react/folder-open';
import { Replay } from '@primeicons/react/replay';
import { Save } from '@primeicons/react/save';
import { Undo } from '@primeicons/react/undo';
import { Menu, MenuGroup, MenuItem, MenuList, MenuPopup, MenuPortal, MenuPositioner, MenuSeparator } from '@/components/ui/menu';
import { Menubar, MenubarTrigger } from '@/components/ui/menubar';
const Shortcut = ({ children }: { children: React.ReactNode }) => (
<span className="ms-auto text-xs text-surface-500 dark:text-surface-400">{children}</span>
);
export default function BasicDemo() {
return (
<div className="flex justify-center">
<Menubar>
<Menu>
<MenubarTrigger>File</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-44">
<MenuList>
<MenuGroup>
<MenuItem>
<File />
New Document <Shortcut>⌘ N</Shortcut>
</MenuItem>
<MenuItem>
<FolderOpen />
Open <Shortcut>⌘ O</Shortcut>
</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>
<Save />
Save <Shortcut>⌘ S</Shortcut>
</MenuItem>
<MenuItem>
<Download />
Save As… <Shortcut>⇧ ⌘ S</Shortcut>
</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
<Menu>
<MenubarTrigger>Edit</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-44">
<MenuList>
<MenuGroup>
<MenuItem>
<Undo />
Undo <Shortcut>⌘ Z</Shortcut>
</MenuItem>
<MenuItem>
<Replay />
Redo <Shortcut>⇧ ⌘ Z</Shortcut>
</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>
<Clipboard />
Cut <Shortcut>⌘ X</Shortcut>
</MenuItem>
<MenuItem>
<Copy />
Copy <Shortcut>⌘ C</Shortcut>
</MenuItem>
<MenuItem>
<File />
Paste <Shortcut>⌘ V</Shortcut>
</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
<Menu>
<MenubarTrigger>View</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-40">
<MenuList>
<MenuGroup>
<MenuItem>Zoom In</MenuItem>
<MenuItem>Zoom Out</MenuItem>
<MenuItem>Reset Zoom</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>Full Screen</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
<Menu>
<MenubarTrigger>Help</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-44">
<MenuList>
<MenuGroup>
<MenuItem>Documentation</MenuItem>
<MenuItem>Support</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>About</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
</Menubar>
</div>
);
}
With Submenus#
Each Menu inside the bar can contain MenuSub for nested levels.
'use client';
import { ChevronRight } from '@primeicons/react/chevron-right';
import {
Menu,
MenuGroup,
MenuIndicator,
MenuItem,
MenuList,
MenuPopup,
MenuPortal,
MenuPositioner,
MenuSeparator,
MenuSub,
MenuSubTrigger
} from '@/components/ui/menu';
import { Menubar, MenubarTrigger } from '@/components/ui/menubar';
export default function SubmenuDemo() {
return (
<div className="flex justify-center">
<Menubar>
<Menu>
<MenubarTrigger>File</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-44">
<MenuList>
<MenuGroup>
<MenuItem>New File</MenuItem>
<MenuItem>Open File…</MenuItem>
<MenuSub>
<MenuSubTrigger>
Open Recent
<MenuIndicator>
<ChevronRight className="size-3.5" />
</MenuIndicator>
</MenuSubTrigger>
<MenuPortal>
<MenuPositioner>
<MenuPopup className="w-40">
<MenuList>
<MenuGroup>
<MenuItem>todo.md</MenuItem>
<MenuItem>changelog.md</MenuItem>
<MenuItem>readme.md</MenuItem>
<MenuSub>
<MenuSubTrigger>
Older
<MenuIndicator>
<ChevronRight className="size-3.5" />
</MenuIndicator>
</MenuSubTrigger>
<MenuPortal>
<MenuPositioner>
<MenuPopup className="w-40">
<MenuList>
<MenuGroup>
<MenuItem>release-notes.md</MenuItem>
<MenuItem>roadmap.md</MenuItem>
<MenuItem>contributing.md</MenuItem>
<MenuItem>license.txt</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuSub>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>Clear Recent</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</MenuSub>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>Save</MenuItem>
<MenuItem>Save As…</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
<Menu>
<MenubarTrigger>View</MenubarTrigger>
<MenuPortal>
<MenuPositioner sideOffset={4}>
<MenuPopup className="w-44">
<MenuList>
<MenuGroup>
<MenuItem>Reload</MenuItem>
<MenuItem>Force Reload</MenuItem>
</MenuGroup>
<MenuSeparator />
<MenuGroup>
<MenuItem>Toggle DevTools</MenuItem>
</MenuGroup>
</MenuList>
</MenuPopup>
</MenuPositioner>
</MenuPortal>
</Menu>
</Menubar>
</div>
);
}
API#
Sub-components#
See Primitive API for Menubar props (orientation, loopFocus, modal, disabled).
MenubarTrigger is a thin wrapper around Menu.Trigger; the underlying API is identical — see Menu for trigger props.
Accessibility#
Screen Reader#
Menubar follows the WAI-ARIA Menubar pattern with role="menubar" and aria-orientation. Each MenubarTrigger exposes aria-haspopup="true" and aria-expanded to announce open/closed state to assistive technology.
Keyboard Support#
Triggers and items participate in roving focus across the bar.
| Key | Function |
|---|---|
right arrow / left arrow | Move focus to the next / previous trigger (loops by default). |
home / end | Move focus to the first / last trigger. |
down arrow / enter / space | Open the focused trigger's menu and move focus to its first item. |
up arrow | Open the focused trigger's menu and move focus to its last item. |
escape | Close the open menu and return focus to its trigger. |
| Any printable character | While a menu is open, jump to the next item starting with the character. |
When a menu is already open, hovering another trigger automatically switches the open menu to it.