caliper uidocs

Menubar

Free

File, Edit and View for an app that works like a desktop program: one highlight glides along the bar, and once a menu is open, moving along opens the next.

Installs components/ui/menubar.tsxDepends on @radix-ui/react-dropdown-menu, @radix-ui/react-menubar, lucide-reactMotion none in component source
pnpm dlx shadcn@latest add https://caliperui.site/r/menubar.json

Field notes from the October close. Revenue landed two days early; the Lisbon office is now on the shared ledger.

Last command: Nothing yet

When to use #

Use it for

  • Editors and tools with many commands grouped by menu.
  • Desktop web apps where people expect menus with shortcuts.

Skip it when

  • A handful of actions; use buttons or a dropdown menu.
  • Site navigation; use the navigation menu.

Installation #

terminal
pnpm dlx shadcn@latest add https://caliperui.site/r/menubar.json

Adds its 5 files to components/ui/, each with its own stylesheet, and installs their packages. No account needed. The first part also adds Caliper UI’s tokens; import them once as in Installation.

Usage #

example.tsx
import { useState } from "react"
import { Menubar, MenubarCheckboxItem, MenubarContent, MenubarItem, MenubarMenu, MenubarRadioGroup, MenubarRadioItem, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubContent, MenubarSubTrigger, MenubarTrigger } from "@/components/ui/menubar"

const shortcuts = [
  { action: "Search everything", keys: "mod+k" },
  { action: "New issue", keys: "c" },
  { action: "Go to inbox", keys: ["g", "i"], then: true },
  { action: "Send comment", keys: "mod+enter" },
  { action: "Move selection", keys: ["alt", "up"] },
  { action: "Close panel", keys: "esc" },
];

export function MenubarDemo() {
  const [ruler, setRuler] = useState(true);
  const [count, setCount] = useState(false);
  const [zoom, setZoom] = useState("100");
  const [last, setLast] = useState("Nothing yet");
  const run = (label: string) => () => setLast(label);
  const words = "Field notes from the October close. Revenue landed two days early; the Lisbon office is now on the shared ledger.";
  return (
    <div className="grid w-full max-w-2xl gap-3">
      <Menubar>
        <MenubarMenu>
          <MenubarTrigger>File</MenubarTrigger>
          <MenubarContent>
            <MenubarItem onSelect={run("New document")}>New document <MenubarShortcut keys="mod+n" /></MenubarItem>
            <MenubarItem onSelect={run("Open")}>Open… <MenubarShortcut keys="mod+o" /></MenubarItem>
            <MenubarSub>
              <MenubarSubTrigger>Open recent</MenubarSubTrigger>
              <MenubarSubContent>
                <MenubarItem onSelect={run("Opened October close")}>October close</MenubarItem>
                <MenubarItem onSelect={run("Opened Hiring plan")}>Hiring plan 2027</MenubarItem>
                <MenubarItem onSelect={run("Opened Board memo")}>Board memo</MenubarItem>
              </MenubarSubContent>
            </MenubarSub>
            <MenubarSeparator />
            <MenubarItem onSelect={run("Saved")}>Save <MenubarShortcut keys="mod+s" /></MenubarItem>
            <MenubarSub>
              <MenubarSubTrigger>Export as</MenubarSubTrigger>
              <MenubarSubContent>
                <MenubarItem onSelect={run("Exported PDF")}>PDF</MenubarItem>
                <MenubarItem onSelect={run("Exported Markdown")}>Markdown</MenubarItem>
                <MenubarItem onSelect={run("Exported Word")}>Word document</MenubarItem>
              </MenubarSubContent>
            </MenubarSub>
            <MenubarSeparator />
            <MenubarItem disabled>Print… <MenubarShortcut keys="mod+p" /></MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>Edit</MenubarTrigger>
          <MenubarContent>
            <MenubarItem onSelect={run("Undo")}>Undo <MenubarShortcut keys="mod+z" /></MenubarItem>
            <MenubarItem onSelect={run("Redo")}>Redo <MenubarShortcut keys="mod+shift+z" /></MenubarItem>
            <MenubarSeparator />
            <MenubarItem onSelect={run("Cut")}>Cut <MenubarShortcut keys="mod+x" /></MenubarItem>
            <MenubarItem onSelect={run("Copy")}>Copy <MenubarShortcut keys="mod+c" /></MenubarItem>
            <MenubarItem onSelect={run("Paste")}>Paste <MenubarShortcut keys="mod+v" /></MenubarItem>
            <MenubarSeparator />
            <MenubarItem onSelect={run("Find")}>Find… <MenubarShortcut keys="mod+f" /></MenubarItem>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>View</MenubarTrigger>
          <MenubarContent>
            <MenubarCheckboxItem checked={ruler} onCheckedChange={setRuler}>Show ruler</MenubarCheckboxItem>
            <MenubarCheckboxItem checked={count} onCheckedChange={setCount}>Show word count</MenubarCheckboxItem>
            <MenubarSeparator />
            <MenubarRadioGroup value={zoom} onValueChange={setZoom}>
              <MenubarRadioItem value="75">Zoom 75%</MenubarRadioItem>
              <MenubarRadioItem value="100">Zoom 100%</MenubarRadioItem>
              <MenubarRadioItem value="125">Zoom 125%</MenubarRadioItem>
            </MenubarRadioGroup>
          </MenubarContent>
        </MenubarMenu>
        <MenubarMenu>
          <MenubarTrigger>Help</MenubarTrigger>
          <MenubarContent>
            <MenubarItem onSelect={run("Opened shortcuts")}>Keyboard shortcuts <MenubarShortcut keys="mod+/" /></MenubarItem>
            <MenubarItem onSelect={run("Opened what's new")}>What’s new</MenubarItem>
          </MenubarContent>
        </MenubarMenu>
      </Menubar>
      <div className="grid gap-2 rounded-[12px] border border-border p-4">
        {ruler && <div aria-hidden="true" className="h-3 bg-[repeating-linear-gradient(90deg,var(--border-strong)_0_1px,transparent_1px_24px)] opacity-60" />}
        <p className="max-w-[60ch] leading-relaxed" style={{ fontSize: `${(14 * Number(zoom)) / 100}px` }}>{words}</p>
        {count && <p className="text-xs text-muted-foreground">{words.split(/\s+/u).length} words</p>}
      </div>
      <p role="status" className="text-[13px] text-muted-foreground">Last command: {last}</p>
    </div>
  );
}

API reference #

Menubar

component

No props of its own; it accepts the native props of its root element.

MenubarMenu

component

No props of its own; it accepts the native props of its root element.

MenubarTrigger

component

No props of its own; it accepts the native props of its root element.

MenubarContent

component

No props of its own; it accepts the native props of its root element.

MenubarItem

component

No props of its own; it accepts the native props of its root element.

MenubarCheckboxItem

component

No props of its own; it accepts the native props of its root element.

MenubarRadioGroup

component

No props of its own; it accepts the native props of its root element.

MenubarRadioItem

component

No props of its own; it accepts the native props of its root element.

MenubarGroup

component

No props of its own; it accepts the native props of its root element.

MenubarLabel

component

No props of its own; it accepts the native props of its root element.

MenubarSeparator

component

No props of its own; it accepts the native props of its root element.

MenubarShortcut

component
PropTypeDefault
keys *string—
classNamestring—

MenubarSub

component

No props of its own; it accepts the native props of its root element.

MenubarSubTrigger

component

No props of its own; it accepts the native props of its root element.

MenubarSubContent

component

No props of its own; it accepts the native props of its root element.

Accessibility #

It is built on native elements and keeps aria-hidden in step with state.

Keyboard and focus handling comes from Radix dropdown-menu and menubar: arrow keys move through items, Enter and Space select, and Escape closes and returns focus.

Motion #

It declares no animation in its component source. Any transition comes from its stylesheet, which uses the duration tokens that collapse to instant under prefers-reduced-motion.