Menubar
A visually persistent menu common in desktop applications.
Preview
Loading...
import {
Menubar,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarItem,
MenubarSeparator,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSubContent,
MenubarSubTrigger,
MenubarSub,
MenubarShortcut,
} from "@/components/ui/Menubar";
export function MenubarDemo() {
return (
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent className="w-20">
<MenubarItem>
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
</MenubarItem>
<MenubarItem>
New Window <MenubarShortcut>⌘N</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled>New Incognito Window</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Share</MenubarSubTrigger>
<MenubarSubContent className="w-20">
<MenubarItem>Email link</MenubarItem>
<MenubarItem>Messages</MenubarItem>
<MenubarItem>Notes</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>
Print... <MenubarShortcut>⌘P</MenubarShortcut>
</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Edit</MenubarTrigger>
<MenubarContent className="w-20">
<MenubarItem>
Undo <MenubarShortcut>⌘Z</MenubarShortcut>
</MenubarItem>
<MenubarItem>
Redo <MenubarShortcut>⇧⌘Z</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarSub>
<MenubarSubTrigger>Find</MenubarSubTrigger>
<MenubarSubContent className="w-20">
<MenubarItem>Search the web</MenubarItem>
<MenubarSeparator />
<MenubarItem>Find...</MenubarItem>
<MenubarItem>Find Next</MenubarItem>
<MenubarItem>Find Previous</MenubarItem>
</MenubarSubContent>
</MenubarSub>
<MenubarSeparator />
<MenubarItem>Cut</MenubarItem>
<MenubarItem>Copy</MenubarItem>
<MenubarItem>Paste</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>View</MenubarTrigger>
<MenubarContent className="w-20">
<MenubarCheckboxItem>Always Show Bookmarks Bar</MenubarCheckboxItem>
<MenubarCheckboxItem checked>Always Show Full URLs</MenubarCheckboxItem>
<MenubarSeparator />
<MenubarItem>
Reload <MenubarShortcut>⌘R</MenubarShortcut>
</MenubarItem>
<MenubarItem disabled>
Force Reload <MenubarShortcut>⇧⌘R</MenubarShortcut>
</MenubarItem>
<MenubarSeparator />
<MenubarItem>Toggle Fullscreen</MenubarItem>
<MenubarSeparator />
<MenubarItem>Hide Sidebar</MenubarItem>
</MenubarContent>
</MenubarMenu>
<MenubarMenu>
<MenubarTrigger>Profiles</MenubarTrigger>
<MenubarContent className="w-20">
<MenubarRadioGroup value="benoit">
<MenubarRadioItem value="andy">Andy</MenubarRadioItem>
<MenubarRadioItem value="benoit">Benoit</MenubarRadioItem>
<MenubarRadioItem value="Luis">Luis</MenubarRadioItem>
</MenubarRadioGroup>
<MenubarSeparator />
<MenubarItem>Edit...</MenubarItem>
<MenubarSeparator />
<MenubarItem>Add Profile...</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>
)
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/menubarManual
Install the following dependencies:
pnpm install @radix-ui/react-icons radix-uiCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the Menubar component into your components/ui/Menubar.tsx file.
"use client";
/**
* @description A visually persistent menu common in desktop applications.
*/
import * as React from "react";
import { Menubar as MenubarRadix } from "radix-ui";
import {
CheckIcon,
ChevronRightIcon,
DotFilledIcon,
} from "@radix-ui/react-icons";
import { cn } from "@/utils/class-names";
function Menubar({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Root>) {
return (
<MenubarRadix.Root
data-slot="menubar"
className={cn("flex", className)}
{...props}
/>
);
}
function MenubarMenu({
...props
}: React.ComponentProps<typeof MenubarRadix.Menu>) {
return <MenubarRadix.Menu data-slot="menubar-menu" {...props} />;
}
function MenubarGroup({
...props
}: React.ComponentProps<typeof MenubarRadix.Group>) {
return <MenubarRadix.Group data-slot="menubar-group" {...props} />;
}
function MenubarPortal({
...props
}: React.ComponentProps<typeof MenubarRadix.Portal>) {
return <MenubarRadix.Portal data-slot="menubar-portal" {...props} />;
}
function MenubarRadioGroup({
...props
}: React.ComponentProps<typeof MenubarRadix.RadioGroup>) {
return <MenubarRadix.RadioGroup data-slot="menubar-radio-group" {...props} />;
}
function MenubarTrigger({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Trigger>) {
return (
<MenubarRadix.Trigger
data-slot="menubar-trigger"
className={cn(
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer",
className
)}
{...props}
/>
);
}
function MenubarContent({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Content>) {
return (
<MenubarPortal>
<MenubarRadix.Content
data-slot="menubar-content"
className={cn(
"bg-gray-1 border border-gray-a6 rounded-sm relative shadow-md",
className
)}
{...props}
/>
</MenubarPortal>
);
}
function MenubarItem({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Item>) {
return (
<MenubarRadix.Item
data-slot="menubar-item"
className={cn(
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer justify-between",
className
)}
{...props}
/>
);
}
function MenubarCheckboxItem({
children,
className,
...props
}: React.ComponentProps<typeof MenubarRadix.CheckboxItem>) {
return (
<MenubarRadix.CheckboxItem
data-slot="menubar-checkbox-item"
className={cn(
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer",
className
)}
{...props}
>
<span className="absolute left-0.5 top-0 bottom-0 items-center flex justify-center">
<MenubarRadix.ItemIndicator>
<CheckIcon className="text-accent-9" />
</MenubarRadix.ItemIndicator>
</span>
{children}
</MenubarRadix.CheckboxItem>
);
}
function MenubarRadioItem({
children,
className,
...props
}: React.ComponentProps<typeof MenubarRadix.RadioItem>) {
return (
<MenubarRadix.RadioItem
data-slot="menubar-radio-item"
className={cn(
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer",
className
)}
{...props}
>
<span className="absolute left-0.5 top-0 bottom-0 items-center flex justify-center">
<MenubarRadix.ItemIndicator>
<DotFilledIcon className="fill-current text-accent-9" />
</MenubarRadix.ItemIndicator>
</span>
{children}
</MenubarRadix.RadioItem>
);
}
function MenubarLabel({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Label>) {
return (
<MenubarRadix.Label
data-slot="menubar-label"
className={cn("p-0.5 px-2 text-gray-12", className)}
{...props}
/>
);
}
function MenubarSeparator({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.Separator>) {
return (
<MenubarRadix.Separator
data-slot="menubar-separator"
className={cn("m-0.6 h-px bg-gray-a6", className)}
{...props}
/>
);
}
function MenubarShortcut({ ...props }: React.ComponentProps<"span">) {
return <span data-slot="menubar-shortcut" {...props} />;
}
function MenubarSub({
...props
}: React.ComponentProps<typeof MenubarRadix.Sub>) {
return <MenubarRadix.Sub data-slot="menubar-sub" {...props} />;
}
function MenubarSubTrigger({
children,
className,
...props
}: React.ComponentProps<typeof MenubarRadix.SubTrigger> & {
inset?: boolean;
}) {
return (
<MenubarRadix.SubTrigger
data-slot="menubar-sub-trigger"
className={cn(
"p-0.5 px-2 hover:bg-accent-3 flex relative cursor-pointer",
className
)}
{...props}
>
{children}
<div className="absolute right-0.5 top-0 bottom-0 items-center flex justify-center">
<ChevronRightIcon />
</div>
</MenubarRadix.SubTrigger>
);
}
function MenubarSubContent({
className,
...props
}: React.ComponentProps<typeof MenubarRadix.SubContent>) {
return (
<MenubarRadix.SubContent
data-slot="menubar-sub-content"
className={cn(
"bg-gray-1 border border-gray-a6 rounded-sm relative shadow-md",
className
)}
{...props}
/>
);
}
export {
Menubar,
MenubarPortal,
MenubarMenu,
MenubarTrigger,
MenubarContent,
MenubarGroup,
MenubarSeparator,
MenubarLabel,
MenubarItem,
MenubarShortcut,
MenubarCheckboxItem,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSub,
MenubarSubTrigger,
MenubarSubContent,
};