Menubar
A frame row of words on a hairline; opening a word folds the line down into a pocket that holds its menu.
Report an issue with MenubarExample
Rest
Pointed at
Focus
Disabled
Caption, rest
Caption, pointed at
Leaders, pointed at
Install
Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base, dropdown-menu, and popover along.
npx shadcn@latest add https:// thedirectors.agency/ ui/ r/menubar.jsonUsage
"use client"import * as React from "react"import {Menubar,MenubarCheckboxItem,MenubarContent,MenubarItem,MenubarLabel,MenubarMenu,MenubarSeparator,MenubarShortcut,MenubarSub,MenubarSubContent,MenubarSubTrigger,MenubarTrigger,} from "@/components/ui/menubar"function Editor({ label, variant }: { label: string; variant?: "pocket" | "leaders" | "caption" }) {const [notes, setNotes] = React.useState(true)const [grid, setGrid] = React.useState(false)return (<Menubar aria-label={label} variant={variant}><MenubarMenu><MenubarTrigger>File</MenubarTrigger><MenubarContent><MenubarItem>New note <MenubarShortcut>⌘N</MenubarShortcut></MenubarItem><MenubarItem>Open <MenubarShortcut>⌘O</MenubarShortcut></MenubarItem><MenubarSeparator /><MenubarLabel>Recent</MenubarLabel><MenubarItem>Northlight</MenubarItem><MenubarItem>Oda Studio</MenubarItem><MenubarSeparator /><MenubarSub><MenubarSubTrigger>Export</MenubarSubTrigger><MenubarSubContent><MenubarItem>As PDF</MenubarItem><MenubarItem>As Markdown</MenubarItem></MenubarSubContent></MenubarSub></MenubarContent></MenubarMenu><MenubarMenu><MenubarTrigger>Edit</MenubarTrigger><MenubarContent><MenubarItem>Undo <MenubarShortcut>⌘Z</MenubarShortcut></MenubarItem><MenubarItem disabled>Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut></MenubarItem><MenubarSeparator /><MenubarItem>Copy <MenubarShortcut>⌘C</MenubarShortcut></MenubarItem><MenubarItem>Paste <MenubarShortcut>⌘V</MenubarShortcut></MenubarItem></MenubarContent></MenubarMenu><MenubarMenu><MenubarTrigger>View</MenubarTrigger><MenubarContent><MenubarCheckboxItem checked={notes} onCheckedChange={setNotes}>Show margin notes</MenubarCheckboxItem><MenubarCheckboxItem checked={grid} onCheckedChange={setGrid}>Show the grid <MenubarShortcut>G</MenubarShortcut></MenubarCheckboxItem></MenubarContent></MenubarMenu></Menubar>)}export default function Example() {return (<div className="grid w-full gap-10"><div className="grid gap-3"><span className="ot-label">Pocket</span><Editor label="Editor" /></div><div className="grid gap-3"><span className="ot-label">Leaders</span><Editor label="Editor, as contents" variant="leaders" /></div><div className="grid gap-3"><span className="ot-label">Caption</span><Editor label="Spring notes" variant="caption" /></div></div>)}/** The bar at rest, pointed at, focused and with a word disabled. Open, see the specimen above. */function Words({ label, force, disabled, variant }: { label: string; force?: "hover" | "focus"; disabled?: boolean; variant?: "caption" }) {return (<Menubar aria-label={label} variant={variant} style={variant ? { width: "min(26rem, 80vw)" } : undefined}><MenubarMenu><MenubarTrigger data-force={force === "focus" ? force : undefined}>File</MenubarTrigger></MenubarMenu><MenubarMenu><MenubarTrigger data-force={force === "hover" ? force : undefined} disabled={disabled}>Edit</MenubarTrigger></MenubarMenu><MenubarMenu><MenubarTrigger>View</MenubarTrigger></MenubarMenu></Menubar>)}Contract
- Underneath: Radix DropdownMenu, ContextMenu and Menubar.
- Anatomy:
<div class="ot-pop ot-menu" popover role="menu">holding.ot-menu-labelheadings and<button class="ot-menu-item" role="menuitem">(ormenuitemcheckboxwitharia-checked), each with optional.ot-menu-keys.data-variant="danger"for a destructive item. A menubar is<div class="ot-menubar" role="menubar">of.ot-menubar-triggerbuttons on a hairline; each menu is aot-menuhung in that hairline. A context menu is anot-menuwithdata-at="point", placed where the person pressed. - The item you point at is marked with the highlighter. Items arrive in turn. A menubar opens its hairline into a pocket under the open word: the menu rises over the rule, its paper hides the rule there, and its sides and foot carry the same line on, down, along and back up. The word and its menu are one shape, with no leader and no stroke. The menu unrolls down out of the line and rolls back up into it. Its words stand under the word, and the bar's words sit in from the rule's ends by a menu's own inset, so the first menu folds from the rule too. With no room below, it turns above the words in a whole frame. Focus on a word is the accent stroke laid on the rule under it. A context menu spreads from the point like ink (
ot-spread); it opens toward the line's end and down from the point, back from it without room, and on a phone slides in to fit. A submenu opens beside its item; on a narrow screen, with room on neither side, it drops open under the item, in by the words' inset, the next level of an outline, and hangs from the item on the popover's leader (data-drop): the dot on the marked item's foot, the line dropping over a strip of paper. The item's arrow turns down while it is open. Shortcut keys (dir="ltr") read ⌘Z in either direction. Without adir, each menu takes the direction of the page around its trigger or bar, so on a right-to-left page it hangs from the right end, submenus open to the left, and the arrow keys mirror. varianton the list (DropdownMenuContent,ContextMenuContent;data-variant):list(the default) orleaders, and alsomarginaliaon a dropdown menu ororbiton a context menu. On theMenubarroot:pocket(the default),leadersorcaption. Under every variant a context menu's point is pinned by a cross, the register mark of "the uncreative", over the menu's corner, and the menu spreads from it.- leaders: a book's contents page. Each word is joined to its keys (or a submenu's arrow) by a row of leader dots in
rule-strong; a word with neither has none, and the words don't wrap. The highlighter stands down: the word you point at inks, and its dots ink from the word to its keys, passing through as the highlighter does. Submenus keep the leaders. A menubar set toleaderssets every menu so, in its pocket. - marginalia (dropdown menu): the small notes on hairline arrows of "It has to be design.". Each item's
hintis a note (pp, graphite, at most 13em) hung beside the list at the height of the word you point at, on a hairline arrow pointing back at it; it glides from word to word, and a word without a hint leaves the margin empty. The list keeps its highlighter. With no room beside the list (under 220px) the note stands under it as its caption, without the arrow. The note is aria-hidden: each item carries its hint as itsaria-description. - orbit (context menu): after WOVE. The words stand on an arc bowed away from the point, one dot on the arc for each; the one you point at inks and its dot lands as the accent. The arc is the panel's edge: the paper lies only outside it, and the panel's hairline and shadow stand down. Every row is one step high, and the words swing out to the arc as they arrive. Put items straight in the list (a group counts as one step); a separator is a step of silence with a short rule in it. In forced colours the arc gives way to a framed panel and the dots stay.
- caption (menubar): the label at the far end of the SHAPES / GRADIENTS frame, and an editor's status line. The bar's far end keeps a small line of where you are, the path from the open word to the item you point at, parted by slashes (File / Export / As PDF); its last step inks and arrives as you move. At rest it shows the bar's
aria-labelin pencil. Below 40rem only the last step shows. It is aria-hidden, since the menus already name the path. - Forced colours: the highlighter gives way to the system's
Highlight; leaders' dots and the marginalia arrow areCanvasText; orbit's pointed dot isHighlight. Reduced motion: the dots, the note and the caption move straight to their places. - Keyboard: Down and Up move, Home and End go to the ends, Enter runs, Escape closes, Tab closes and moves on. Right opens a submenu and Left closes it (mirrored right to left). In a menubar, Down opens, and Left and Right move between menus, open or closed. The context menu opens with the ContextMenu key or Shift+F10.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
MenubarMenu | Radix | One word and its menu: a MenubarTrigger and a MenubarContent. | |
MenubarContent align / sideOffset / alignOffset | Radix | "start" / -1.5 / -27 | The menu wears the dropdown menu's list, hung in the bar's own hairline: it rises over the rule so its paper hides it there, and its sides and foot carry the line on. Its words stand under the word that opened it. With no room below it turns above the words in a whole frame. |
variant | "pocket" | "leaders" | "caption" | "pocket" | pocket: the menus are plain lists in the folded pocket. leaders: the menus are set as a contents page, each word joined to its keys by leader dots. caption: the bar's far end keeps a status line of where you are (File / Export / As PDF), its last step arriving as you move; at rest it shows the bar's name. On a phone only the last step shows. Screen readers already hear the path, so the caption is hidden from them. |
value / onValueChange | string | Which menu is open, when you want to control it. | |
dir | "ltr" | "rtl" | Left to right or right to left. Without it the bar takes the direction of the page around it, so the menus and the arrow keys follow. | |
Keyboard | keys | Down opens. Left and Right move between menus, open or closed. Escape closes and returns focus to the word. |
Craft
Where its move comes from
| Component | Reference | Move |
|---|---|---|
| Menubar | SHAPES / GRADIENTS frame; the folder tab | A frame row of words on a hairline that opens into a pocket under the word |
| Leaders menu | A book's contents page | Leader dots join each word to its keys |
| Caption menubar | SHAPES / GRADIENTS frame label; an editor's status line | The path to where you are, at the bar's far end |
How it moves
| Component | Articulation | What moves |
|---|---|---|
| Menubar | The rule folds down around the open menu and back up; the menu unrolls out of it and rolls back in | |
| Leaders menu | Pass-through | The dots of the word you point at ink from the word to its keys and leave the same way |
| Caption menubar | Arrive | The path's last step arrives as you move |