Skip to main content
A context menu displays a list of actions when users right-click or long-press on an element, supporting nested submenus, checkboxes, radio groups, and keyboard navigation.

Installation

npm install @kuzenbo/core

Usage

Basic Example

import { ContextMenu } from "@kuzenbo/core";

export default function ContextMenuExample() {
  return (
    <ContextMenu>
      <ContextMenu.Trigger className="border border-dashed rounded-md p-8">
        Right-click this area
      </ContextMenu.Trigger>
      <ContextMenu.Content>
        <ContextMenu.Item>Open incident timeline</ContextMenu.Item>
        <ContextMenu.Item>Assign incident owner</ContextMenu.Item>
        <ContextMenu.Separator />
        <ContextMenu.Item variant="danger">Archive incident</ContextMenu.Item>
      </ContextMenu.Content>
    </ContextMenu>
  );
}

With Submenu

import { ContextMenu } from "@kuzenbo/core";

export default function SubmenuExample() {
  return (
    <ContextMenu>
      <ContextMenu.Trigger className="border border-dashed rounded-md p-8">
        Right-click for options
      </ContextMenu.Trigger>
      <ContextMenu.Content>
        <ContextMenu.Group>
          <ContextMenu.Label>Team permissions</ContextMenu.Label>
          <ContextMenu.Item>Edit profile</ContextMenu.Item>
          <ContextMenu.Sub>
            <ContextMenu.SubTrigger>Change role</ContextMenu.SubTrigger>
            <ContextMenu.SubContent>
              <ContextMenu.Item>Viewer</ContextMenu.Item>
              <ContextMenu.Item>Editor</ContextMenu.Item>
              <ContextMenu.Item>Admin</ContextMenu.Item>
            </ContextMenu.SubContent>
          </ContextMenu.Sub>
        </ContextMenu.Group>
        <ContextMenu.Separator />
        <ContextMenu.Item variant="danger">Remove from workspace</ContextMenu.Item>
      </ContextMenu.Content>
    </ContextMenu>
  );
}

With Checkbox Items

import { ContextMenu } from "@kuzenbo/core";

export default function CheckboxExample() {
  return (
    <ContextMenu>
      <ContextMenu.Trigger className="border border-dashed rounded-md p-8">
        Right-click for column settings
      </ContextMenu.Trigger>
      <ContextMenu.Content>
        <ContextMenu.Group>
          <ContextMenu.Label>Column visibility</ContextMenu.Label>
          <ContextMenu.CheckboxItem defaultChecked>
            Status column
          </ContextMenu.CheckboxItem>
          <ContextMenu.CheckboxItem defaultChecked>
            Owner column
          </ContextMenu.CheckboxItem>
          <ContextMenu.CheckboxItem>
            Age column
          </ContextMenu.CheckboxItem>
        </ContextMenu.Group>
      </ContextMenu.Content>
    </ContextMenu>
  );
}

With Disabled Items

import { ContextMenu } from "@kuzenbo/core";

export default function DisabledExample() {
  return (
    <ContextMenu>
      <ContextMenu.Trigger className="border border-dashed rounded-md p-8">
        Right-click for actions
      </ContextMenu.Trigger>
      <ContextMenu.Content>
        <ContextMenu.Item>Create hotfix</ContextMenu.Item>
        <ContextMenu.Item disabled>
          Delete branch (missing permission)
        </ContextMenu.Item>
        <ContextMenu.Separator />
        <ContextMenu.Item disabled variant="danger">
          Force push (admin only)
        </ContextMenu.Item>
      </ContextMenu.Content>
    </ContextMenu>
  );
}

Composed Anatomy

import { ContextMenu } from "@kuzenbo/core";

export default function ComposedContext() {
  return (
    <ContextMenu>
      <ContextMenu.Trigger className="border border-dashed rounded-md p-8">
        Right-click here
      </ContextMenu.Trigger>
      <ContextMenu.Portal>
        <ContextMenu.Backdrop />
        <ContextMenu.Positioner>
          <ContextMenu.Popup>
            <ContextMenu.Arrow />
            <ContextMenu.Group>
              <ContextMenu.Label>Card actions</ContextMenu.Label>
              <ContextMenu.Item>Open details</ContextMenu.Item>
              <ContextMenu.LinkItem href="/docs">
                View documentation
              </ContextMenu.LinkItem>
            </ContextMenu.Group>
            <ContextMenu.Separator />
            <ContextMenu.Item variant="danger">
              Remove from sprint
            </ContextMenu.Item>
          </ContextMenu.Popup>
        </ContextMenu.Positioner>
      </ContextMenu.Portal>
    </ContextMenu>
  );
}

API Reference

ContextMenu (Root)

defaultOpen
boolean
The initial open state when uncontrolled.
open
boolean
The controlled open state of the menu.
onOpenChange
(open: boolean) => void
Callback fired when the open state changes.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
default:"'md'"
The size variant for the menu.

ContextMenu.Content

side
'top' | 'right' | 'bottom' | 'left'
default:"'right'"
The preferred side of the cursor to render against.
sideOffset
number
default:"0"
The distance in pixels from the cursor.
align
'start' | 'center' | 'end'
default:"'start'"
The alignment of the menu relative to the cursor.
alignOffset
number
default:"4"
The offset in pixels from the alignment axis.
size
'xs' | 'sm' | 'md' | 'lg' | 'xl'
Override the root size for this content.
className
string
Additional CSS classes to apply.

ContextMenu.Trigger

children
ReactNode
The content that will trigger the context menu on right-click.
className
string
Additional CSS classes to apply.

ContextMenu.Item

variant
'default' | 'danger'
default:"'default'"
The visual variant of the item.
disabled
boolean
Whether the item is disabled.
onSelect
() => void
Callback fired when the item is selected.

ContextMenu.CheckboxItem

checked
boolean
The controlled checked state.
defaultChecked
boolean
The initial checked state when uncontrolled.
onCheckedChange
(checked: boolean) => void
Callback fired when the checked state changes.

ContextMenu.RadioGroup

value
string
The controlled value of the selected radio item.
defaultValue
string
The initial value when uncontrolled.
onValueChange
(value: string) => void
Callback fired when the value changes.

ContextMenu.RadioItem

value
string
required
The value of this radio item.

ContextMenu.LinkItem

href
string
required
The URL to navigate to.

ContextMenu.Label

children
ReactNode
The label content.

ContextMenu.Separator

Visual separator between menu items.

ContextMenu.Shortcut

children
ReactNode
The keyboard shortcut text.

Component Parts

  • ContextMenu - Root component that manages state
  • ContextMenu.Trigger - Element that triggers the menu on right-click
  • ContextMenu.Portal - Portals the menu content
  • ContextMenu.Positioner - Positions the menu at cursor location
  • ContextMenu.Popup - The menu container
  • ContextMenu.Content - Convenience wrapper
  • ContextMenu.Item - A menu item
  • ContextMenu.CheckboxItem - A checkable menu item
  • ContextMenu.RadioGroup - Groups radio items
  • ContextMenu.RadioItem - A radio menu item
  • ContextMenu.LinkItem - A navigation menu item
  • ContextMenu.Label - A non-interactive label
  • ContextMenu.Separator - Visual separator
  • ContextMenu.Shortcut - Keyboard shortcut indicator
  • ContextMenu.Sub - Submenu root
  • ContextMenu.SubTrigger - Opens a submenu
  • ContextMenu.SubContent - Submenu content
  • ContextMenu.Group - Groups related items
  • ContextMenu.Arrow - Visual arrow indicator
  • ContextMenu.Backdrop - Optional backdrop overlay

Accessibility

  • Full keyboard navigation support
  • Arrow keys navigate between items
  • Enter or Space activates items
  • Escape closes the menu
  • Type-ahead to focus items
  • Proper ARIA attributes
  • Focus management on open/close
  • Supports both right-click and long-press gestures

Build docs developers (and LLMs) love