Components
Base Components
Context Menu
A menu that appears on right-click or long-press for contextual actions.
Example
Right click here
Installation
Install the following dependencies:
npm install radix-uinpm install lucide-reactCreate a context-menu.tsx file and paste the following code into it.
"use client"import * as React from "react"import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"import { ContextMenu as ContextMenuPrimitive } from "radix-ui"import { cn } from "@/lib/utils"function ContextMenu({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Root>) { return <ContextMenuPrimitive.Root data-slot="context-menu" {...props} />}function ContextMenuTrigger({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Trigger>) { return ( <ContextMenuPrimitive.Trigger data-slot="context-menu-trigger" {...props} /> )}function ContextMenuGroup({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Group>) { return ( <ContextMenuPrimitive.Group data-slot="context-menu-group" {...props} /> )}function ContextMenuPortal({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Portal>) { return ( <ContextMenuPrimitive.Portal data-slot="context-menu-portal" {...props} /> )}function ContextMenuSub({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Sub>) { return <ContextMenuPrimitive.Sub data-slot="context-menu-sub" {...props} />}function ContextMenuRadioGroup({ ...props}: React.ComponentProps<typeof ContextMenuPrimitive.RadioGroup>) { return ( <ContextMenuPrimitive.RadioGroup data-slot="context-menu-radio-group" {...props} /> )}function ContextMenuSubTrigger({ className, inset, children, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.SubTrigger> & { inset?: boolean}) { return ( <ContextMenuPrimitive.SubTrigger data-slot="context-menu-sub-trigger" data-inset={inset} className={cn( "text-primary focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-primary flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} {...props} > {children} <ChevronRightIcon className="ml-auto" /> </ContextMenuPrimitive.SubTrigger> )}function ContextMenuSubContent({ className, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.SubContent>) { return ( <ContextMenuPrimitive.SubContent data-slot="context-menu-sub-content" 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 data-[side=bottom]:slide-in-from-top-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 z-50 min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", className )} {...props} /> )}function ContextMenuContent({ className, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Content> & { dir?: React.HTMLAttributes<HTMLDivElement>["dir"]}) { return ( <ContextMenuPrimitive.Portal> <ContextMenuPrimitive.Content data-slot="context-menu-content" 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 data-[side=bottom]:slide-in-from-top-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 z-50 max-h-(--radix-context-menu-content-available-height) min-w-[8rem] origin-(--radix-context-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", className )} {...props} /> </ContextMenuPrimitive.Portal> )}function ContextMenuItem({ className, inset, variant = "default", ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Item> & { inset?: boolean variant?: "default" | "destructive"}) { return ( <ContextMenuPrimitive.Item data-slot="context-menu-item" data-inset={inset} data-variant={variant} className={cn( "text-primary focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-primary relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", className )} {...props} /> )}function ContextMenuCheckboxItem({ className, children, checked, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.CheckboxItem>) { return ( <ContextMenuPrimitive.CheckboxItem data-slot="context-menu-checkbox-item" className={cn( "text-primary focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none 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 left-2 flex size-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <CheckIcon className="size-4" /> </ContextMenuPrimitive.ItemIndicator> </span> {children} </ContextMenuPrimitive.CheckboxItem> )}function ContextMenuRadioItem({ className, children, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.RadioItem>) { return ( <ContextMenuPrimitive.RadioItem data-slot="context-menu-radio-item" className={cn( "text-primary focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none 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 left-2 flex size-3.5 items-center justify-center"> <ContextMenuPrimitive.ItemIndicator> <CircleIcon className="size-2 fill-current" /> </ContextMenuPrimitive.ItemIndicator> </span> {children} </ContextMenuPrimitive.RadioItem> )}function ContextMenuLabel({ className, inset, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Label> & { inset?: boolean}) { return ( <ContextMenuPrimitive.Label data-slot="context-menu-label" data-inset={inset} className={cn( "text-menu-heading px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", className )} {...props} /> )}function ContextMenuSeparator({ className, ...props}: React.ComponentProps<typeof ContextMenuPrimitive.Separator>) { return ( <ContextMenuPrimitive.Separator data-slot="context-menu-separator" className={cn("bg-border -mx-1 my-1 h-px", className)} {...props} /> )}function ContextMenuShortcut({ className, ...props}: React.ComponentProps<"span">) { return ( <span data-slot="context-menu-shortcut" className={cn( "text-primary ml-auto text-xs tracking-widest", className )} {...props} /> )}export { ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuPortal, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuRadioGroup,}Check the import paths to ensure they match your project setup.
Usage
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu";<ContextMenu>
<ContextMenuTrigger>Right click here</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Profile</ContextMenuItem>
<ContextMenuItem>Billing</ContextMenuItem>
<ContextMenuItem>Team</ContextMenuItem>
<ContextMenuItem>Subscription</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>Examples
Basic
A simple context menu with a few actions.Right click here
Submenu
UseContextMenuSub, ContextMenuSubTrigger, and ContextMenuSubContent to nest secondary actions.
Right click here
Shortcuts
AddContextMenuShortcut to show keyboard hints.
Right click here
Groups
Group related actions withContextMenuGroup and separate them with ContextMenuSeparator.
Right click here
Icons
Combine icons with labels for quick scanning.Right click here
Checkboxes
UseContextMenuCheckboxItem for toggles. Control checked state with checked and onCheckedChange.
Right click here
Radio
UseContextMenuRadioGroup and ContextMenuRadioItem for exclusive choices.
Right click here
Destructive
Usevariant="destructive" on ContextMenuItem for destructive actions.
Right click here
RTL
Right-to-left layout with translated labels. Wrap the trigger area in a container withdir="rtl".
انقر بزر الماوس الأيمن هنا
API Reference
The Context Menu composes Radix primitives:ContextMenu, ContextMenuTrigger, ContextMenuContent, ContextMenuItem, ContextMenuCheckboxItem, ContextMenuRadioItem, ContextMenuRadioGroup, ContextMenuLabel, ContextMenuSeparator, ContextMenuShortcut, ContextMenuGroup, ContextMenuSub, ContextMenuSubTrigger, and ContextMenuSubContent. See the Radix Context Menu documentation for behavior and accessibility details.