# Context Menu

A menu that appears on right-click, providing contextual actions for the target element.

> For the complete documentation index, see [llms.txt](/llms.txt). Markdown variants are available by appending `.md` to any URL or sending an `Accept: text/markdown` header. An agent skill is available at [/.well-known/agent-skills/site-skill.md](/.well-known/agent-skills/site-skill.md).





<ComponentThemeTabs>
  <ThemeTab name="mint">
    <PreviewWithCode name="context-menu">
      <ContextMenuDemo />
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="berries">
    <PreviewWithCode name="context-menu">
      <ContextMenuDemo />
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="citrine">
    <PreviewWithCode name="context-menu">
      <ContextMenuDemo />
    </PreviewWithCode>
  </ThemeTab>

  <ThemeTab name="cinnamon">
    <PreviewWithCode name="context-menu">
      <ContextMenuDemo />
    </PreviewWithCode>
  </ThemeTab>
</ComponentThemeTabs>

## With Checkboxes [#with-checkboxes]

Use `ContextMenuCheckboxItem` for toggleable items that show a check when active.

```tsx
"use client";

import { useState } from "react";
import {
  ContextMenu,
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuLabel,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@/components/ui/context-menu";

export function ContextMenuCheckboxDemo() {
  const [showBookmarks, setShowBookmarks] = useState(true);
  const [showURLs, setShowURLs] = useState(false);

  return (
    <ContextMenu>
      <ContextMenuTrigger className="flex h-32 w-64 items-center justify-center rounded-md border border-dashed text-sm text-muted-foreground">
        Right-click here
      </ContextMenuTrigger>
      <ContextMenuContent className="w-48">
        <ContextMenuLabel>View</ContextMenuLabel>
        <ContextMenuSeparator />
        <ContextMenuCheckboxItem
          checked={showBookmarks}
          onCheckedChange={setShowBookmarks}
        >
          Show Bookmarks Bar
        </ContextMenuCheckboxItem>
        <ContextMenuCheckboxItem
          checked={showURLs}
          onCheckedChange={setShowURLs}
        >
          Show Full URLs
        </ContextMenuCheckboxItem>
      </ContextMenuContent>
    </ContextMenu>
  );
}
```

## With Radio Items [#with-radio-items]

Use `ContextMenuRadioGroup` + `ContextMenuRadioItem` for mutually exclusive options.

```tsx
"use client";

import { useState } from "react";
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuLabel,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from "@/components/ui/context-menu";

export function ContextMenuRadioDemo() {
  const [position, setPosition] = useState("top");

  return (
    <ContextMenu>
      <ContextMenuTrigger className="flex h-32 w-64 items-center justify-center rounded-md border border-dashed text-sm text-muted-foreground">
        Right-click here
      </ContextMenuTrigger>
      <ContextMenuContent className="w-48">
        <ContextMenuLabel>Panel Position</ContextMenuLabel>
        <ContextMenuSeparator />
        <ContextMenuRadioGroup value={position} onValueChange={setPosition}>
          <ContextMenuRadioItem value="top">Top</ContextMenuRadioItem>
          <ContextMenuRadioItem value="right">Right</ContextMenuRadioItem>
          <ContextMenuRadioItem value="bottom">Bottom</ContextMenuRadioItem>
        </ContextMenuRadioGroup>
      </ContextMenuContent>
    </ContextMenu>
  );
}
```

## Props [#props]

### ContextMenuItem [#contextmenuitem]

| Prop        | Type                         | Default     | Description                                |
| ----------- | ---------------------------- | ----------- | ------------------------------------------ |
| `variant`   | `"default" \| "destructive"` | `"default"` | Destructive styles for dangerous actions   |
| `inset`     | `boolean`                    | `false`     | Adds left padding to align with icon items |
| `disabled`  | `boolean`                    | `false`     | Prevents selection                         |
| `onSelect`  | `(event: Event) => void`     | —           | Callback when item is selected             |
| `className` | `string`                     | —           | Additional CSS classes                     |

### ContextMenuSubTrigger [#contextmenusubtrigger]

| Prop    | Type      | Default | Description                                |
| ------- | --------- | ------- | ------------------------------------------ |
| `inset` | `boolean` | `false` | Adds left padding to align with icon items |

### ContextMenuCheckboxItem [#contextmenucheckboxitem]

| Prop              | Type                         | Default | Description                 |
| ----------------- | ---------------------------- | ------- | --------------------------- |
| `checked`         | `boolean \| "indeterminate"` | —       | Controlled checked state    |
| `onCheckedChange` | `(checked: boolean) => void` | —       | Callback when state changes |

### ContextMenuRadioItem [#contextmenuradioitem]

| Prop    | Type     | Default | Description               |
| ------- | -------- | ------- | ------------------------- |
| `value` | `string` | —       | Value for the radio group |

### ContextMenuLabel [#contextmenulabel]

| Prop    | Type      | Default | Description       |
| ------- | --------- | ------- | ----------------- |
| `inset` | `boolean` | `false` | Adds left padding |

## Usage [#usage]

```tsx
import {
  ContextMenu,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuSeparator,
  ContextMenuShortcut,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from "@/components/ui/context-menu";

<ContextMenu>
  <ContextMenuTrigger>Right-click me</ContextMenuTrigger>
  <ContextMenuContent className="w-48">
    <ContextMenuItem>
      Copy
      <ContextMenuShortcut>⌘C</ContextMenuShortcut>
    </ContextMenuItem>
    <ContextMenuItem>
      Paste
      <ContextMenuShortcut>⌘V</ContextMenuShortcut>
    </ContextMenuItem>
    <ContextMenuSeparator />
    <ContextMenuSub>
      <ContextMenuSubTrigger>More</ContextMenuSubTrigger>
      <ContextMenuSubContent>
        <ContextMenuItem>Select All</ContextMenuItem>
      </ContextMenuSubContent>
    </ContextMenuSub>
    <ContextMenuSeparator />
    <ContextMenuItem variant="destructive">Delete</ContextMenuItem>
  </ContextMenuContent>
</ContextMenu>
```

## Specs [#specs]

```md
# Mint — Context Menu Specs

## Component
- name: context-menu
- file: registry/mint/context-menu.tsx
- installs to: components/ui/context-menu.tsx
- dependencies: radix-ui, lucide-react
- registryDependencies: none

## What is it
A floating menu triggered by the browser's right-click (contextmenu) event on
a wrapped element. Use it for file/item actions, editor operations, or any
surface where right-click is a natural interaction pattern. Do not use it for
primary navigation — prefer DropdownMenu for pointer-initiated menus.

## Visual identity
Popover-surfaced panel with rounded-md corners and a 1px border. Compact item
rows (py-1.5, text-sm) with accent-coloured hover/focus states. Matches the
Mint palette's soft green wash — a light green tint appears only on focus or
the destructive variant.

## Design tokens
--popover: oklch(1 0 0) / oklch(0.269 0 0)             — menu panel background
--popover-foreground: oklch(0.145 0 0) / oklch(0.985 0 0) — default item text
--accent: oklch(0.92 0.05 155) / oklch(0.26 0.05 155)            — hover/focus item bg
--accent-foreground: oklch(0.32 0.1 155) / oklch(0.88 0.06 155) — hover/focus item text
--muted-foreground: oklch(0.52 0.06 155) / oklch(0.6 0.06 155)  — shortcut + icon colour
--destructive: oklch(0.55 0.25 15) / oklch(0.704 0.191 22.216) — danger item text
--border: oklch(0.88 0.04 155 / 60%) / oklch(0.32 0.05 155 / 40%)          — panel border + separator
--foreground: oklch(0.145 0 0) / oklch(0.985 0 0)        — label text

## Sub-components
- ContextMenu             → root provider, no visual output
- ContextMenuTrigger      → wraps the right-clickable area
- ContextMenuPortal       → renders content into a portal
- ContextMenuContent      → floating menu panel (rendered via Portal automatically)
- ContextMenuGroup        → semantic grouping wrapper, no visual output
- ContextMenuItem         → action row; accepts variant and inset props
- ContextMenuCheckboxItem → toggleable item with CheckIcon indicator
- ContextMenuRadioGroup   → wraps radio items, holds value + onValueChange
- ContextMenuRadioItem    → mutually exclusive option with CircleIcon indicator
- ContextMenuLabel        → non-interactive section heading (font-medium)
- ContextMenuSeparator    → 1px horizontal rule between groups
- ContextMenuShortcut     → right-aligned keyboard hint (ml-auto, display only)
- ContextMenuSub          → sub-menu root
- ContextMenuSubTrigger   → item that opens a sub-menu (ChevronRightIcon auto-appended)
- ContextMenuSubContent   → floating panel for sub-menu items

## Variants
- default     → standard item style; accent bg + text on focus
- destructive → text-destructive at rest; destructive/10 (light) or destructive/20 (dark) bg on focus

## States
- focus:      bg-accent + text-accent-foreground on all interactive items
- data-[state=open]: SubTrigger shows accent bg + text while sub-menu is open
- data-[disabled]: pointer-events-none + opacity-50 on items and checkbox/radio items
- data-[checked]: ItemIndicator renders CheckIcon (checkbox) or CircleIcon (radio) when active

## Conventions
- Set a fixed width on ContextMenuContent: className="w-48" or "w-56"
- ContextMenuContent already renders inside a Portal — do not wrap it in ContextMenuPortal manually
- Use inset={true} on ContextMenuItem, ContextMenuLabel, or ContextMenuSubTrigger to add pl-8 and align text with icon-prefixed siblings
- ContextMenuShortcut is display-only — wire actual keyboard shortcuts separately (e.g. useEffect + keydown)
- ContextMenuTrigger wraps any element; no interactive element required
- Always nest ContextMenuSubContent inside a ContextMenuSub root
- Sub-components expose data-slot="[name]" attributes for CSS targeting
```

## Installation [#installation]

<CommandBox componentName="context-menu" className="mt-2" />
