MC Context Menu
A menu that appears on right-click or long press.
Overview
The mc-context-menu is a context menu component for MicroClub UI. Built on the @base-ui/react context menu primitive, it provides accessible right-click and long-press interactions with MicroClub styling via Tailwind CSS v4.
As a part of the MicroClub library, this component is designed for instant deployment into your codebase, giving you full ownership of its look and behavior.
Preview
import { McContextMenu, McContextMenuCheckboxItem, McContextMenuContent, McContextMenuGroup, McContextMenuItem, McContextMenuLabel, McContextMenuRadioGroup, McContextMenuRadioItem, McContextMenuSeparator, McContextMenuShortcut, McContextMenuSub, McContextMenuSubContent, McContextMenuSubTrigger, McContextMenuTrigger,} from '@/registry/ui/mc-context-menu';export default function McContextMenuDemo() { return ( <McContextMenu> <McContextMenuTrigger className="flex h-40 w-72 items-center justify-center rounded-lg border border-dashed border-border bg-card text-sm text-muted-foreground"> Right click here </McContextMenuTrigger> <McContextMenuContent className="w-56"> <McContextMenuGroup> <McContextMenuLabel>Actions</McContextMenuLabel> <McContextMenuItem> Back <McContextMenuShortcut>Alt+Left</McContextMenuShortcut> </McContextMenuItem> <McContextMenuItem> Forward <McContextMenuShortcut>Alt+Right</McContextMenuShortcut> </McContextMenuItem> <McContextMenuItem disabled>Reload</McContextMenuItem> </McContextMenuGroup> <McContextMenuSub> <McContextMenuSubTrigger>More tools</McContextMenuSubTrigger> <McContextMenuSubContent> <McContextMenuItem>Save page as...</McContextMenuItem> <McContextMenuItem>Create shortcut...</McContextMenuItem> <McContextMenuItem>Inspect</McContextMenuItem> </McContextMenuSubContent> </McContextMenuSub> <McContextMenuSeparator /> <McContextMenuCheckboxItem checked>Show bookmarks</McContextMenuCheckboxItem> <McContextMenuCheckboxItem>Show full URLs</McContextMenuCheckboxItem> <McContextMenuSeparator /> <McContextMenuGroup> <McContextMenuLabel inset>Density</McContextMenuLabel> <McContextMenuRadioGroup value="comfortable"> <McContextMenuRadioItem value="compact">Compact</McContextMenuRadioItem> <McContextMenuRadioItem value="comfortable">Comfortable</McContextMenuRadioItem> </McContextMenuRadioGroup> </McContextMenuGroup> </McContextMenuContent> </McContextMenu> );}Add to Your Project
Deploy the mc-context-menu directly to your components/ui directory:
Manual Setup
If you prefer manual control:
'use client';import * as React from 'react';import { ContextMenu as ContextMenuPrimitive } from '@base-ui/react/context-menu';import { CheckIcon, ChevronRightIcon } from 'lucide-react';import { cn } from '@/lib/utils';function McContextMenu({ ...props }: ContextMenuPrimitive.Root.Props) { return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />;}function McContextMenuPortal({ ...props }: ContextMenuPrimitive.Portal.Props) { return <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} />;}function McContextMenuTrigger({ className, ...props }: ContextMenuPrimitive.Trigger.Props) { return ( <ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" className={cn('select-none', className)} {...props} /> );}function McContextMenuContent({ className, align = 'start', alignOffset = 4, side = 'right', sideOffset = 0, ...props}: ContextMenuPrimitive.Popup.Props & Pick<ContextMenuPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) { return ( <ContextMenuPrimitive.Portal> <ContextMenuPrimitive.Positioner className="isolate z-50 outline-none" align={align} alignOffset={alignOffset} side={side} sideOffset={sideOffset} > <ContextMenuPrimitive.Popup data-slot="context-menu-content" className={cn( 'z-50 max-h-(--available-height) min-w-36 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover p-1 text-popover-foreground shadow-md ring-1 ring-border duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95', className )} {...props} /> </ContextMenuPrimitive.Positioner> </ContextMenuPrimitive.Portal> );}function McContextMenuGroup({ ...props }: ContextMenuPrimitive.Group.Props) { return <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} />;}function McContextMenuLabel({ className, inset, ...props}: ContextMenuPrimitive.GroupLabel.Props & { inset?: boolean;}) { return ( <ContextMenuPrimitive.GroupLabel data-slot="context-menu-label" data-inset={inset} className={cn( 'px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7', className )} {...props} /> );}function McContextMenuItem({ className, inset, variant = 'default', ...props}: ContextMenuPrimitive.Item.Props & { inset?: boolean; variant?: 'default' | 'destructive';}) { return ( <ContextMenuPrimitive.Item data-slot="context-menu-item" data-inset={inset} data-variant={variant} className={cn( "group/context-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:*:[svg]:text-accent-foreground data-[variant=destructive]:*:[svg]:text-destructive", className )} {...props} /> );}function McContextMenuSub({ ...props }: ContextMenuPrimitive.SubmenuRoot.Props) { return <ContextMenuPrimitive.SubmenuRoot data-slot="context-menu-sub" {...props} />;}function McContextMenuSubTrigger({ className, inset, children, ...props}: ContextMenuPrimitive.SubmenuTrigger.Props & { inset?: boolean;}) { return ( <ContextMenuPrimitive.SubmenuTrigger data-slot="context-menu-sub-trigger" data-inset={inset} className={cn( "flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} {...props} > {children} <ChevronRightIcon className="cn-rtl-flip ml-auto" /> </ContextMenuPrimitive.SubmenuTrigger> );}function McContextMenuSubContent({ ...props }: React.ComponentProps<typeof McContextMenuContent>) { return ( <McContextMenuContent data-slot="context-menu-sub-content" className="shadow-lg" side="right" {...props} /> );}function McContextMenuCheckboxItem({ className, children, checked, inset, ...props}: ContextMenuPrimitive.CheckboxItem.Props & { inset?: boolean;}) { return ( <ContextMenuPrimitive.CheckboxItem data-slot="context-menu-checkbox-item" data-inset={inset} className={cn( "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} checked={checked} {...props} > <span className="pointer-events-none absolute right-2"> <ContextMenuPrimitive.CheckboxItemIndicator> <CheckIcon /> </ContextMenuPrimitive.CheckboxItemIndicator> </span> {children} </ContextMenuPrimitive.CheckboxItem> );}function McContextMenuRadioGroup({ ...props }: ContextMenuPrimitive.RadioGroup.Props) { return <ContextMenuPrimitive.RadioGroup data-slot="context-menu-radio-group" {...props} />;}function McContextMenuRadioItem({ className, children, inset, ...props}: ContextMenuPrimitive.RadioItem.Props & { inset?: boolean;}) { return ( <ContextMenuPrimitive.RadioItem data-slot="context-menu-radio-item" data-inset={inset} className={cn( "relative flex cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none focus:bg-accent focus:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} {...props} > <span className="pointer-events-none absolute right-2"> <ContextMenuPrimitive.RadioItemIndicator> <CheckIcon /> </ContextMenuPrimitive.RadioItemIndicator> </span> {children} </ContextMenuPrimitive.RadioItem> );}function McContextMenuSeparator({ className, ...props }: ContextMenuPrimitive.Separator.Props) { return ( <ContextMenuPrimitive.Separator data-slot="context-menu-separator" className={cn('-mx-1 my-1 h-px bg-border', className)} {...props} /> );}function McContextMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) { return ( <span data-slot="context-menu-shortcut" className={cn( 'ml-auto text-xs tracking-widest text-muted-foreground group-focus/context-menu-item:text-accent-foreground', className )} {...props} /> );}export { McContextMenu, McContextMenuTrigger, McContextMenuContent, McContextMenuItem, McContextMenuCheckboxItem, McContextMenuRadioItem, McContextMenuLabel, McContextMenuSeparator, McContextMenuShortcut, McContextMenuGroup, McContextMenuPortal, McContextMenuSub, McContextMenuSubContent, McContextMenuSubTrigger, McContextMenuRadioGroup,};Ensure your @/lib/utils or equivalent classname helper is correctly imported.
Usage
import {
McContextMenu,
McContextMenuContent,
McContextMenuItem,
McContextMenuTrigger,
} from '@/components/ui/mc-context-menu';
export default function Example() {
return (
<McContextMenu>
<McContextMenuTrigger>Right click here</McContextMenuTrigger>
<McContextMenuContent>
<McContextMenuItem>Back</McContextMenuItem>
<McContextMenuItem>Forward</McContextMenuItem>
<McContextMenuItem>Reload</McContextMenuItem>
</McContextMenuContent>
</McContextMenu>
);
}Examples
With Groups and Labels
<McContextMenu>
<McContextMenuTrigger>Right click here</McContextMenuTrigger>
<McContextMenuContent>
<McContextMenuGroup>
<McContextMenuLabel>Actions</McContextMenuLabel>
<McContextMenuItem>Back</McContextMenuItem>
<McContextMenuItem>Forward</McContextMenuItem>
<McContextMenuItem disabled>Reload</McContextMenuItem>
</McContextMenuGroup>
</McContextMenuContent>
</McContextMenu>With Shortcuts
<McContextMenuItem>
Back
<McContextMenuShortcut>Alt+Left</McContextMenuShortcut>
</McContextMenuItem>With Checkbox Items
<McContextMenuCheckboxItem checked>Show bookmarks</McContextMenuCheckboxItem>
<McContextMenuCheckboxItem>Show full URLs</McContextMenuCheckboxItem>With Radio Items
<McContextMenuGroup>
<McContextMenuLabel inset>Density</McContextMenuLabel>
<McContextMenuRadioGroup value="comfortable">
<McContextMenuRadioItem value="compact">Compact</McContextMenuRadioItem>
<McContextMenuRadioItem value="comfortable">Comfortable</McContextMenuRadioItem>
<McContextMenuRadioItem value="spacious">Spacious</McContextMenuRadioItem>
</McContextMenuRadioGroup>
</McContextMenuGroup>With Submenus
<McContextMenuSub>
<McContextMenuSubTrigger>More tools</McContextMenuSubTrigger>
<McContextMenuSubContent>
<McContextMenuItem>Save page as...</McContextMenuItem>
<McContextMenuItem>Create shortcut...</McContextMenuItem>
<McContextMenuItem>Inspect</McContextMenuItem>
</McContextMenuSubContent>
</McContextMenuSub>API Reference
McContextMenu
The root component that manages context menu state.
All props from @base-ui/react/context-menu Root are supported.
McContextMenuTrigger
The element that opens the context menu on right-click or long press.
All props from @base-ui/react/context-menu Trigger are supported.
McContextMenuContent
The floating menu panel.
| Prop | Type | Default | Description |
|---|---|---|---|
side | "top" | "bottom" | "left" | "right" | "right" | Preferred side of the trigger to open on |
sideOffset | number | 0 | Distance in px from the trigger |
align | "start" | "center" | "end" | "start" | Alignment along the trigger axis |
alignOffset | number | 4 | Offset in px along the alignment axis |
className | string | undefined | Additional CSS classes |
All other props from @base-ui/react/context-menu Popup are supported.
McContextMenuItem
An actionable menu item.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | Adds left padding for alignment |
variant | "default" | "destructive" | "default" | Visual style for the item |
className | string | undefined | Additional CSS classes |
disabled | boolean | undefined | Disables item interaction |
All other props from @base-ui/react/context-menu Item are supported.
McContextMenuLabel
A label for a menu group.
McContextMenuLabel must be used inside McContextMenuGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | Adds left padding for alignment |
className | string | undefined | Additional CSS classes |
McContextMenuGroup
Groups related menu items and labels.
All props from @base-ui/react/context-menu Group are supported.
McContextMenuCheckboxItem
A checkable menu item.
| Prop | Type | Default | Description |
|---|---|---|---|
checked | boolean | undefined | Checked state |
inset | boolean | undefined | Adds alignment padding |
className | string | undefined | Additional CSS classes |
McContextMenuRadioGroup
Groups mutually exclusive radio menu items.
All props from @base-ui/react/context-menu RadioGroup are supported.
McContextMenuRadioItem
A selectable radio item inside McContextMenuRadioGroup.
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | Required | Radio item value |
inset | boolean | undefined | Adds alignment padding |
className | string | undefined | Additional CSS classes |
McContextMenuSub
The root component for a nested submenu.
All props from @base-ui/react/context-menu SubmenuRoot are supported.
McContextMenuSubTrigger
The item that opens a nested submenu.
| Prop | Type | Default | Description |
|---|---|---|---|
inset | boolean | undefined | Adds left padding for alignment |
className | string | undefined | Additional CSS classes |
McContextMenuSubContent
The floating panel for a submenu.
All props from McContextMenuContent are supported.
McContextMenuSeparator
A visual separator between menu sections.
All props from @base-ui/react/context-menu Separator are supported.
McContextMenuShortcut
Displays shortcut text aligned to the end of a menu item.
All props from span are supported.