Menubar
Desktop-style horizontal menu bar with nested menus, checkbox and radio items.
pnpm dlx @glinui/cli@latest add menubarInstallation
pnpm dlx @glinui/cli@latest add menubarPrefer the package?
Usage
View toggles
Checkbox and radio items for editor settings. Press the arrow keys to move between menus.
export function Header() {
return <nav aria-label="Main" />
}
"use client"
import * as React from "react"import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarLabel, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarTrigger} from "@glinui/ui"
function EditorWindow({ open, children }: { open: "file" | "view"; children: React.ReactNode }) { return ( <div className="mx-auto min-h-80 w-full max-w-2xl overflow-hidden rounded-xl border border-[var(--line-soft)] bg-[var(--surface-1)] [box-shadow:var(--elev-1)]"> <div className="flex items-center gap-3 border-b border-[var(--line-soft)] px-2 py-1.5"> <span className="ps-1 text-xs font-semibold" aria-hidden="true">{`{ }`}</span> <Menubar defaultValue={open} className="border-0 bg-transparent p-0 [box-shadow:none]"> {children} </Menubar> </div> <div className="grid gap-1 p-4 font-mono text-xs leading-6 text-[var(--color-muted)]"> <p><span className="text-[var(--color-accent)]">export</span> function Header() {"{"}</p> <p className="ps-4"><span className="text-[var(--color-accent)]">return</span> {"<nav aria-label=\"Main\" />"}</p> <p>{"}"}</p> </div> </div> )}
export function MenubarViewExample() { const [minimap, setMinimap] = React.useState(true) const [wrap, setWrap] = React.useState(false) const [theme, setTheme] = React.useState("dark") return ( <EditorWindow open="view"> <MenubarMenu value="file"> <MenubarTrigger>File</MenubarTrigger> <MenubarContent><MenubarItem>New file</MenubarItem></MenubarContent> </MenubarMenu> <MenubarMenu value="view"> <MenubarTrigger>View</MenubarTrigger> <MenubarContent className="w-60"> <MenubarLabel>Editor</MenubarLabel> <MenubarCheckboxItem checked={minimap} onCheckedChange={setMinimap}>Minimap</MenubarCheckboxItem> <MenubarCheckboxItem checked={wrap} onCheckedChange={setWrap}>Word wrap <MenubarShortcut>Alt Z</MenubarShortcut></MenubarCheckboxItem> <MenubarSeparator /> <MenubarLabel>Color theme</MenubarLabel> <MenubarRadioGroup value={theme} onValueChange={setTheme}> <MenubarRadioItem value="light">Light</MenubarRadioItem> <MenubarRadioItem value="dark">Dark</MenubarRadioItem> </MenubarRadioGroup> </MenubarContent> </MenubarMenu> </EditorWindow> )}Variants
Every look of the shared vocabulary: glinr (the default), plain (shadcn), solid, soft, outline, ghost, gradient and glass. Omit `variant` to follow the ambient design style.
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarTrigger } from "@glinui/ui"
const variants = ["glinr", "plain", "solid", "soft", "outline", "ghost", "gradient", "glass"] as const
export function Demo() { return ( <div className="grid gap-3 sm:grid-cols-2"> {variants.map((variant) => ( <Menubar key={variant} variant={variant}> <MenubarMenu> <MenubarTrigger>File</MenubarTrigger> <MenubarContent> <MenubarItem>New tab</MenubarItem> <MenubarSeparator /> <MenubarItem>Print</MenubarItem> </MenubarContent> </MenubarMenu> <MenubarMenu> <MenubarTrigger>Edit</MenubarTrigger> <MenubarContent> <MenubarItem>Undo</MenubarItem> <MenubarItem>Redo</MenubarItem> </MenubarContent> </MenubarMenu> </Menubar> ))} </div> )}Glass (opt-in)
Glass is opt-in and needs a colourful or photographic backdrop. Pick one in the stage header.
import { Menubar, MenubarContent, MenubarItem, MenubarMenu, MenubarSeparator, MenubarShortcut, MenubarTrigger } from "@glinui/ui"
export function Demo() { return ( <Menubar variant="glass"> <MenubarMenu> <MenubarTrigger>File</MenubarTrigger> <MenubarContent> <MenubarItem>New tab <MenubarShortcut>Cmd T</MenubarShortcut></MenubarItem> <MenubarItem>New window</MenubarItem> <MenubarSeparator /> <MenubarItem>Print</MenubarItem> </MenubarContent> </MenubarMenu> <MenubarMenu> <MenubarTrigger>Edit</MenubarTrigger> <MenubarContent> <MenubarItem>Undo</MenubarItem> <MenubarItem>Redo</MenubarItem> </MenubarContent> </MenubarMenu> </Menubar> )}Accessibility
- Uses the WAI-ARIA menubar pattern with roving focus.
- Check and radio items expose their checked state.
- Panels render in a portal and restore focus on close.
Keyboard Interactions
| Key | Action |
|---|---|
| ArrowLeft / ArrowRight | Move between menu triggers. |
| ArrowDown | Open the menu and focus the first item. |
| ArrowUp / ArrowDown | Move between items. |
| Enter / Space | Select the focused item. |
| Escape | Close the menu. |
ARIA Attributes
- `role="menubar"`, `menu`, `menuitem`
- `aria-checked` on checkbox and radio items
- `aria-haspopup` and `aria-expanded` on triggers
Reduced Motion
Panels fade and scale from 95% on open using transform and opacity only. With prefers-reduced-motion the animation is removed.
Affected properties
opacitytransformAPI Reference
Menubar
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
variant | MenubarVariant | No | ambient style (glinr) | Bar and panel surface. Omit it for the ambient design style; the open trigger and highlighted items are raised pills in the glinr look. `glass` is opt-in and needs a backdrop. |
value | string | - | - | Controlled open menu value. |
onValueChange | (value: string) => void | - | - | Called when the open menu changes. |
loop | boolean | - | false | Loop keyboard focus across triggers. |
MenubarItem and friends
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
inset | boolean | - | false | Item and label: add start padding to align with items that have indicators. |
disabled | boolean | - | false | Item: blocks selection and focus. |
onSelect | (event: Event) => void | - | - | Item: called on selection. |
variant | MenubarVariant | No | - | Surface look. Defaults to the bar's variant, then the ambient design style. |
Source
Import directly from the package or browse the source on GitHub. Click any file to view it.
Import
import { Menubar } from "@glinui/ui"Source Files
Dependencies
@glinui/ui@phosphor-icons/react@radix-ui/react-menubarclass-variance-authorityGenerated API Snapshot
Beta
Generated API Snapshot
BetaAuto-extracted from TypeScript source in packages/ui/src/components/menubar.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.
Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata
Primary Props Type
MenubarProps
MenubarContentProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
variant | MenubarVariant | No | - | Surface look. Defaults to the bar's variant, then the ambient design style. |
MenubarProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
variant | MenubarVariant | No | - | Surface look of the bar and its menus. Omit for the ambient design style (glinr by default). |