Skip to main content

context menu

Displays a context menu of actions triggered by right-click on a target.

Philosophy

Context menus are power-user shortcuts that surface relevant actions where the user already is. This implementation is built directly on the @gentleduck/primitives/context-menu primitives, so right-click behavior, keyboard interactions, and submenu semantics stay consistent.

How It's Built

Loading diagram...

Installation


npx @gentleduck/cli add context-menu

npx @gentleduck/cli add context-menu

Usage

import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuTrigger,
} from "@/components/ui/context-menu"
<ContextMenu>
  <ContextMenuTrigger>Right click</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Profile</ContextMenuItem>
    <ContextMenuItem>Billing</ContextMenuItem>
    <ContextMenuItem>Team</ContextMenuItem>
    <ContextMenuItem>Subscription</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>
<ContextMenu>
  <ContextMenuTrigger>Right click</ContextMenuTrigger>
  <ContextMenuContent>
    <ContextMenuItem>Profile</ContextMenuItem>
    <ContextMenuItem>Billing</ContextMenuItem>
    <ContextMenuItem>Team</ContextMenuItem>
    <ContextMenuItem>Subscription</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>

Component Composition

Loading diagram...

Behavior

  • Right-click the trigger area to open the menu.
  • Left-click does not open the menu.
  • Right-clicking outside closes the menu and allows the native browser menu to appear.

RTL Support

Set dir="rtl" on ContextMenu for a local override, or set DirectionProvider once at app/root level for global direction.

Motion

Use MotionContextMenu and MotionContextMenuContent for smooth enter/exit animations powered by motion. The transform origin is fixed to top-left since the menu appears at the cursor position. For animated sub-menus, use MotionContextMenuSub and MotionContextMenuSubContent.

API Reference

Components in this file wrap @gentleduck/primitives/context-menu.

ContextMenu

PropTypeDefaultDescription
childrenReact.ReactNode-Context menu content (trigger + menu content)
modalbooleantrueWhether interaction outside the menu is blocked while open
dir'ltr' | 'rtl'-Text direction. Resolved by primitives useDirection (dir prop -> DirectionProvider -> 'ltr').
onOpenChange(open: boolean) => void-Callback fired when open state changes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Root>-Additional props inherited from ContextMenuPrimitive.Root

ContextMenuTrigger

PropTypeDefaultDescription
disabledbooleanfalseDisables custom context-menu behavior and falls back to native behavior
childrenReact.ReactNode-Trigger area content
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Trigger>-Additional props inherited from ContextMenuPrimitive.Trigger

ContextMenuPortal

PropTypeDefaultDescription
containerHTMLElement-Optional portal container
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Portal>-Additional props inherited from ContextMenuPrimitive.Portal

ContextMenuContent

PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReact.ReactNode-Menu items and groups
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>-Additional props inherited from ContextMenuPrimitive.Content

ContextMenuContent is positioned by the primitive as side="right", align="start", and sideOffset={2}.

ContextMenuItem

PropTypeDefaultDescription
insetbooleanfalseAdds start padding for alignment with items that render indicators/icons
classNamestring-Additional CSS classes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item>-Additional props inherited from ContextMenuPrimitive.Item

ContextMenuCheckboxItem

PropTypeDefaultDescription
checkedboolean-Controlled checked state
onCheckedChange(checked: boolean) => void-Callback when checked state changes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>-Additional props inherited from ContextMenuPrimitive.CheckboxItem

ContextMenuRadioGroup

PropTypeDefaultDescription
valuestring-Controlled selected value
onValueChange(value: string) => void-Callback when selected value changes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioGroup>-Additional props inherited from ContextMenuPrimitive.RadioGroup

ContextMenuRadioItem

PropTypeDefaultDescription
valuestring(required)Value represented by this radio item
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>-Additional props inherited from ContextMenuPrimitive.RadioItem

ContextMenuLabel

PropTypeDefaultDescription
insetbooleanfalseAdds start padding for alignment with items
classNamestring-Additional CSS classes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label>-Additional props inherited from ContextMenuPrimitive.Label

ContextMenuSeparator

PropTypeDefaultDescription
classNamestring-Additional CSS classes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>-Additional props inherited from ContextMenuPrimitive.Separator

ContextMenuShortcut

PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReact.ReactNode-Shortcut hint content (for example, ⌘K)
...propsReact.HTMLAttributes<HTMLSpanElement>-Additional props to spread to the shortcut <span>

ContextMenuGroup

PropTypeDefaultDescription
classNamestring-Additional CSS classes
childrenReact.ReactNode-Group content
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Group>-Additional props inherited from ContextMenuPrimitive.Group

ContextMenuSub

PropTypeDefaultDescription
childrenReact.ReactNode-Sub-trigger and sub-content elements
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Sub>-Additional props inherited from ContextMenuPrimitive.Sub

ContextMenuSubTrigger

PropTypeDefaultDescription
insetbooleanfalseAdds start padding for alignment
classNamestring-Additional CSS classes
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger>-Additional props inherited from ContextMenuPrimitive.SubTrigger

ContextMenuSubContent

PropTypeDefaultDescription
classNamestring-Additional CSS classes
side'top' | 'right' | 'bottom' | 'left'-Preferred side relative to the sub-trigger
align'start' | 'center' | 'end'-Alignment on the chosen side
sideOffsetnumber-Main-axis offset from sub-trigger
alignOffsetnumber-Cross-axis offset from sub-trigger
...propsReact.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>-Additional props inherited from ContextMenuPrimitive.SubContent

MotionContextMenu

Same props as ContextMenu. Wraps with useMotionRoot for exit animation support. Requires the motion package.

MotionContextMenuContent

Same props as ContextMenuContent. Adds scale, blur, and opacity enter/exit animation with springBouncy transition. Transform origin fixed to top-left. Requires the motion package.

MotionContextMenuSub

Same props as ContextMenuSub. Wraps sub-menu with useMotionRoot for exit animation support. Requires the motion package.

MotionContextMenuSubContent

Same props as ContextMenuSubContent. Adds scale and blur enter/exit animation in a Portal. Requires the motion package.