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.

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

RTL Support

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