IX Surfaces

Star on GitHubFeedback
IX SurfacesRadixot-menubar

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 Menubar

Example

Pocket
Leaders
Caption
Rest
Pointed at
Focus
Disabled
Caption, rest
Caption, pointed at
Leaders, pointed at
New note ⌘N
Open ⌘O
Export

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

Usage

menubar-example.tsx
"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-label headings and <button class="ot-menu-item" role="menuitem"> (or menuitemcheckbox with aria-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-trigger buttons on a hairline; each menu is a ot-menu hung in that hairline. A context menu is an ot-menu with data-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 a dir, 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.
  • variant on the list (DropdownMenuContent, ContextMenuContent; data-variant): list (the default) or leaders, and also marginalia on a dropdown menu or orbit on a context menu. On the Menubar root: pocket (the default), leaders or caption. 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 to leaders sets every menu so, in its pocket.
  • marginalia (dropdown menu): the small notes on hairline arrows of "It has to be design.". Each item's hint is 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 its aria-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-label in 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 are CanvasText; orbit's pointed dot is Highlight. 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

Props of Menubar
PropTypeDefaultWhat it does
MenubarMenuRadixOne word and its menu: a MenubarTrigger and a MenubarContent.
MenubarContent align / sideOffset / alignOffsetRadix"start" / -1.5 / -27The 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 / onValueChangestringWhich 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.
KeyboardkeysDown opens. Left and Right move between menus, open or closed. Escape closes and returns focus to the word.

Craft

Where its move comes from

Where its move comes from
ComponentReferenceMove
MenubarSHAPES / GRADIENTS frame; the folder tabA frame row of words on a hairline that opens into a pocket under the word
Leaders menuA book's contents pageLeader dots join each word to its keys
Caption menubarSHAPES / GRADIENTS frame label; an editor's status lineThe path to where you are, at the bar's far end

How it moves

How it moves
ComponentArticulationWhat moves
MenubarPocketThe rule folds down around the open menu and back up; the menu unrolls out of it and rolls back in
Leaders menuPass-throughThe dots of the word you point at ink from the word to its keys and leave the same way
Caption menubarArriveThe path's last step arrives as you move