Glin UI
Primitive / Moleculebeta

Menubar

Desktop-style horizontal menu bar with nested menus, checkbox and radio items.

Edit on GitHub

Installation

Install from
pnpm dlx @glinui/cli@latest add menubar

Prefer 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.

glinr
plain
solid
soft
outline
ghost
gradient
glass
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

KeyAction
ArrowLeft / ArrowRightMove between menu triggers.
ArrowDownOpen the menu and focus the first item.
ArrowUp / ArrowDownMove between items.
Enter / SpaceSelect the focused item.
EscapeClose 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

opacitytransform

API Reference

PropTypeRequiredDefaultDescription
variantMenubarVariantNoambient 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.
valuestring--Controlled open menu value.
onValueChange(value: string) => void--Called when the open menu changes.
loopboolean-falseLoop keyboard focus across triggers.
PropTypeRequiredDefaultDescription
insetboolean-falseItem and label: add start padding to align with items that have indicators.
disabledboolean-falseItem: blocks selection and focus.
onSelect(event: Event) => void--Item: called on selection.
variantMenubarVariantNo-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-authority

Generated API Snapshot

Beta

Auto-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

PropTypeRequiredDefaultDescription
variantMenubarVariantNo-Surface look. Defaults to the bar's variant, then the ambient design style.

MenubarProps

PropTypeRequiredDefaultDescription
variantMenubarVariantNo-Surface look of the bar and its menus. Omit for the ambient design style (glinr by default).