Menubar
An app-style menubar whose menus fade and scale out of their trigger, with a highlight that glides between items.
Preview
Pick something from a menu
Setup
Install with the shadcn CLI
One command adds every file, the npm packages and any Kinetik components it builds on. Needs a components.json; the CLI offers to create one if your project has none.
Or install manually
- 1
Run in your terminal:
$npm install clsx tailwind-merge - 2
Copy
lib/utils.tsfrom the Code tab. Skip if you already havecn(). - 3
Copy
styles/tokens.cssfrom the Code tab and import it in your global CSS after Tailwind:@import "./styles/tokens.css"; - 4
Create a
components/ui/menubar/folder and copy every file from the Code tab into it. Each file does one job, so you can read or change a piece without the rest. - 5
Import and render:
Exampleimport { Menubar } from "@/components/ui/menubar" <Menubar menus={[{ label: "File", items: [{ label: "New file" }] }]} />
Usage
Describe the menus as data. A light pill slides between the triggers as you hover; a menu fades and scales out of the trigger that opened it, and a soft highlight glides between its items. While a menu is open, hovering another trigger switches to it.
import { FilePlus, Save } from "lucide-react"
import { Menubar } from "@/components/ui/menubar"
export function EditorBar() {
const [minimap, setMinimap] = useState(false)
return (
<Menubar
label="Editor"
menus={[
{
label: "File",
items: [
{ type: "label", label: "Document" },
{ label: "New file", icon: <FilePlus />, shortcut: "Ctrl N", onSelect: createFile },
{ type: "submenu", label: "Open recent", items: recentFiles },
{ type: "separator" },
{ label: "Save", icon: <Save />, shortcut: "Ctrl S", onSelect: save },
],
},
{
label: "View",
items: [{ type: "checkbox", label: "Minimap", checked: minimap, onCheckedChange: setMinimap }],
},
]}
/>
)
}
Entries
type | Fields | Notes |
|---|---|---|
(none) or "item" | label, icon?, shortcut?, disabled?, onSelect? | Selecting closes the menu. shortcut is display only. |
"checkbox" | label, checked, onCheckedChange, shortcut? | Stays open when toggled. |
"submenu" | label, icon?, items | Opens to the side on hover, click or Right arrow. |
"label" | label | A small heading for a group. |
"separator" | — | A thin rule between groups. |
Props
| Prop | Type | Default | Notes |
|---|---|---|---|
menus | { label; items: MenubarEntry[] }[] | — | One per trigger. |
label | string | "Menu" | Accessible name for the menubar. |
className | string | — | Applied to the wrapper. |
Accessibility
- A
menubarof triggers, each opening amenuofmenuitemandmenuitemcheckboxrows - One Tab stop on the bar: Left and Right move between triggers; Down, Enter or Space opens a menu
- In a menu: Up and Down move, Home and End jump, Right opens a submenu, Left or Escape goes back
- Closed menus are
inert, so they fade out without being reachable by keyboard or screen readers - Clicking outside closes the menu; with reduced motion, everything changes instantly