Menubar
A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
Installation
Install the following dependencies:
npm install @radix-ui/react-menubarCopy and paste the following code into your project.
'use client';
import * as MenubarPrimitive from '@radix-ui/react-menubar';
import clsx from 'clsx';
import { Check, ChevronRight, Circle } from 'lucide-react';
import { ComponentPropsWithoutRef, ElementRef, HTMLAttributes, forwardRef } from 'react';
import styles from './styles.module.scss';
const MenubarMenu = MenubarPrimitive.Menu;
const MenubarGroup = MenubarPrimitive.Group;
const MenubarPortal = MenubarPrimitive.Portal;
const MenubarSub = MenubarPrimitive.Sub;
const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
const Menubar = forwardRef<
ElementRef<typeof MenubarPrimitive.Root>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Root ref={ref} className={clsx(styles.menubar, className)} {...props} />
));
Menubar.displayName = MenubarPrimitive.Root.displayName;
const MenubarTrigger = forwardRef<
ElementRef<typeof MenubarPrimitive.Trigger>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Trigger ref={ref} className={clsx(styles.menubar__trigger, className)} {...props} />
));
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
const MenubarSubTrigger = forwardRef<
ElementRef<typeof MenubarPrimitive.SubTrigger>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({ className, inset, children, ...props }, ref) => (
<MenubarPrimitive.SubTrigger
ref={ref}
className={clsx(styles.menubar__sub__trigger, inset && styles.menubar__inset, className)}
{...props}
>
{children}
<ChevronRight className={styles.menubar__sub__trigger__icon} />
</MenubarPrimitive.SubTrigger>
));
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
const MenubarSubContent = forwardRef<
ElementRef<typeof MenubarPrimitive.SubContent>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.SubContent ref={ref} className={clsx(styles.menubar__sub__content, className)} {...props} />
));
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
const MenubarContent = forwardRef<
ElementRef<typeof MenubarPrimitive.Content>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
>(({ className, align = 'start', alignOffset = -4, sideOffset = 8, ...props }, ref) => (
<MenubarPrimitive.Portal>
<MenubarPrimitive.Content
ref={ref}
align={align}
alignOffset={alignOffset}
sideOffset={sideOffset}
className={clsx(styles.menubar__content, className)}
{...props}
/>
</MenubarPrimitive.Portal>
));
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
const MenubarItem = forwardRef<
ElementRef<typeof MenubarPrimitive.Item>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Item
ref={ref}
className={clsx(styles.menubar__item, inset && styles.menubar__inset, className)}
{...props}
/>
));
MenubarItem.displayName = MenubarPrimitive.Item.displayName;
const MenubarCheckboxItem = forwardRef<
ElementRef<typeof MenubarPrimitive.CheckboxItem>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
>(({ className, children, checked, ...props }, ref) => (
<MenubarPrimitive.CheckboxItem
ref={ref}
className={clsx(styles.menubar__checkbox__item, className)}
checked={checked}
{...props}
>
<span className={styles.menubar__checkbox__item__check}>
<MenubarPrimitive.ItemIndicator>
<Check className={styles.menubar__checkbox__item__icon} />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.CheckboxItem>
));
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
const MenubarRadioItem = forwardRef<
ElementRef<typeof MenubarPrimitive.RadioItem>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<MenubarPrimitive.RadioItem ref={ref} className={clsx(styles.menubar__radio__item, className)} {...props}>
<span className={styles.menubar__radio__item__circle}>
<MenubarPrimitive.ItemIndicator>
<Circle className={styles.menubar__radio__item__icon} />
</MenubarPrimitive.ItemIndicator>
</span>
{children}
</MenubarPrimitive.RadioItem>
));
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
const MenubarLabel = forwardRef<
ElementRef<typeof MenubarPrimitive.Label>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<MenubarPrimitive.Label
ref={ref}
className={clsx(styles.menubar__label, inset && styles.menubar__inset, className)}
{...props}
/>
));
MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
const MenubarSeparator = forwardRef<
ElementRef<typeof MenubarPrimitive.Separator>,
ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
>(({ className, ...props }, ref) => (
<MenubarPrimitive.Separator ref={ref} className={clsx(styles.menubar__separator, className)} {...props} />
));
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
const MenubarShortcut = ({ className, ...props }: HTMLAttributes<HTMLSpanElement>) => {
return <span className={clsx(styles.menubar__shortcut, className)} {...props} />;
};
MenubarShortcut.displayname = 'MenubarShortcut';
export {
Menubar,
MenubarCheckboxItem,
MenubarContent,
MenubarGroup,
MenubarItem,
MenubarLabel,
MenubarMenu,
MenubarPortal,
MenubarRadioGroup,
MenubarRadioItem,
MenubarSeparator,
MenubarShortcut,
MenubarSub,
MenubarSubContent,
MenubarSubTrigger,
MenubarTrigger,
};Update the import paths to match your project setup.
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</MenubarItem>
<MenubarSeparator />
<MenubarItem>Share</MenubarItem>
<MenubarSeparator />
<MenubarItem>Print</MenubarItem>
</MenubarContent>
</MenubarMenu>
</Menubar>