ComponentsMenubar
Menubar
A horizontal menu bar with dropdown menus. Common in desktop-style application layouts.
Usage
import {
Menubar,
MenubarContent,
MenubarItem,
MenubarMenu,
MenubarSeparator,
MenubarShortcut,
MenubarTrigger,
} from "@/components/ui/menubar"<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarItem>New Tab <MenubarShortcut>⌘T</MenubarShortcut></MenubarItem>
<MenubarItem>New Window <MenubarShortcut>⌘N</MenubarShortcut></MenubarItem>
<MenubarSeparator />
<MenubarItem>Print… <MenubarShortcut>⌘P</MenubarShortcut></MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>Installation
Via CLI
terminal
npx shadcn@latest add https://solar-ui.com/r/menubar.jsonManual
1. Install the dependency:
terminal
npm install @radix-ui/react-menubar2. Copy and paste the following code into your project:
components/ui/menubar.tsx
"use client"
import * as React from "react"
import * as MenubarPrimitive from "@radix-ui/react-menubar"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Menubar({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Root>) {
return (
<MenubarPrimitive.Root
className={cn("flex h-9 items-center gap-1 rounded-md border bg-background p-1 shadow-xs", className)}
{...props}
/>
)
}
function MenubarMenu({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
return <MenubarPrimitive.Menu {...props} />
}
function MenubarTrigger({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
return (
<MenubarPrimitive.Trigger
className={cn("focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default select-none items-center rounded-sm px-2.5 py-1 text-sm font-medium outline-hidden", className)}
{...props}
/>
)
}
function MenubarContent({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }: React.ComponentProps<typeof MenubarPrimitive.Content>) {
return (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
align={align}
alignOffset={alignOffset}
sideOffset={sideOffset}
className={cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 z-50 min-w-48 overflow-hidden rounded-md border p-1 shadow-md", className)}
{...props}
/>
</MenubarPrimitive.Portal>
)
}
function MenubarItem({ className, inset, variant = "default", ...props }: React.ComponentProps<typeof MenubarPrimitive.Item> & { inset?: boolean; variant?: "default" | "destructive" }) {
return (
<MenubarPrimitive.Item
data-inset={inset}
data-variant={variant}
className={cn("focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset=true]:pl-8 [&_svg:not([class*='size-'])]:size-4", className)}
{...props}
/>
)
}
function MenubarCheckboxItem({ className, children, checked, ...props }: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
return (
<MenubarPrimitive.CheckboxItem
className={cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className)}
checked={checked}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator><CheckIcon className="size-4" /></MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.CheckboxItem>
)
}
function MenubarRadioGroup({ ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
return <MenubarPrimitive.RadioGroup {...props} />
}
function MenubarRadioItem({ className, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
return (
<MenubarPrimitive.RadioItem
className={cn("focus:bg-accent focus:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className)}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<MenubarPrimitive.ItemIndicator><CircleIcon className="size-2 fill-current" /></MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.RadioItem>
)
}
function MenubarLabel({ className, inset, ...props }: React.ComponentProps<typeof MenubarPrimitive.Label> & { inset?: boolean }) {
return <MenubarPrimitive.Label className={cn("px-2 py-1.5 text-xs font-medium text-muted-foreground data-[inset=true]:pl-8", className)} data-inset={inset} {...props} />
}
function MenubarSeparator({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.Separator>) {
return <MenubarPrimitive.Separator className={cn("bg-border -mx-1 my-1 h-px", className)} {...props} />
}
function MenubarShortcut({ className, ...props }: React.ComponentProps<"span">) {
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />
}
function MenubarSub({ ...props }: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
return <MenubarPrimitive.Sub {...props} />
}
function MenubarSubTrigger({ className, inset, children, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & { inset?: boolean }) {
return (
<MenubarPrimitive.SubTrigger
data-inset={inset}
className={cn("focus:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden data-[inset=true]:pl-8", className)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto size-4" />
</MenubarPrimitive.SubTrigger>
)
}
function MenubarSubContent({ className, ...props }: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
return (
<MenubarPrimitive.SubContent
className={cn("bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 z-50 min-w-32 overflow-hidden rounded-md border p-1 shadow-lg", className)}
{...props}
/>
)
}
export {
Menubar, MenubarMenu, MenubarTrigger, MenubarContent, MenubarGroup: MenubarPrimitive.Group,
MenubarItem, MenubarCheckboxItem, MenubarRadioGroup, MenubarRadioItem,
MenubarLabel, MenubarSeparator, MenubarShortcut, MenubarSub, MenubarSubTrigger, MenubarSubContent,
}API
Menubar
The root container. Renders a horizontal bar.
MenubarMenu
Wraps a MenubarTrigger and its associated MenubarContent. No props beyond standard HTML.
MenubarTrigger
The button that opens the dropdown.
MenubarItem
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "default" | "destructive" | "default" | Visual style. |
inset | boolean | false | Left-pad to align with items that have icons. |
disabled | boolean | false | Prevent interaction. |
MenubarCheckboxItem
| Prop | Type | Description |
|---|---|---|
checked | boolean | "indeterminate" | Checked state. |
onCheckedChange | (checked: boolean) => void | Callback on change. |
MenubarRadioGroup + MenubarRadioItem
<MenubarRadioGroup value={value} onValueChange={setValue}>
<MenubarRadioItem value="option-a">Option A</MenubarRadioItem>
<MenubarRadioItem value="option-b">Option B</MenubarRadioItem>
</MenubarRadioGroup>MenubarShortcut
A <span> that renders keyboard shortcut hints right-aligned inside a menu item.
Last updated on