---
title: "ContextMenu"
description: "A command menu that opens at the pointer or at given coordinates."
category: Navigation
status: beta
since: 0.3.4
tags: [context, menu, popover]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
Right-clicking the trigger area opens the menu; `trigger="manual"` with `v-model`, `x`, and `y` opens it at given coordinates.
:::TuffDemoWrapper{demo="ContextMenuContextMenuDemo" code-lang="vue"}
---
code: |
  <template>
    <TxContextMenu>
      <template #trigger>
        <div class="zone">Right-click here</div>
      </template>
      <template #menu>
        <TxContextMenuItem shortcut="⌘C" @select="copy">Copy</TxContextMenuItem>
        <TxContextMenuItem shortcut="⌘V" disabled>Paste</TxContextMenuItem>
        <TxContextMenuDivider />
        <TxContextMenuItem danger shortcut="⌫">Delete</TxContextMenuItem>
      </template>
    </TxContextMenu>

    <TxContextMenu v-model="open" trigger="manual" :x="x" :y="y">
      <template #menu>
        <TxContextMenuItem shortcut="⌘N">New file</TxContextMenuItem>
        <TxContextMenuItem :activation-feedback="false">Run immediately</TxContextMenuItem>
      </template>
    </TxContextMenu>

    <TxPopover v-model="panelOpen" placement="bottom-start">
      <template #reference>
        <TxButton>Panel inside Popover</TxButton>
      </template>
      <TxContextMenuPanel :close="() => { panelOpen = false }">
        <TxContextMenuItem color="#10b981">Approve</TxContextMenuItem>
        <TxContextMenuDivider inset />
        <TxContextMenuItem danger>Reject</TxContextMenuItem>
      </TxContextMenuPanel>
    </TxPopover>
  </template>
---
:::

### Anchor Mode
`anchorMode="pointer"` (the default) follows the pointer or the given coordinates; `reference` attaches to the trigger area, like a dropdown.

```vue
<TxContextMenu anchor-mode="pointer" />
<TxContextMenu anchor-mode="reference" />
```

### Submenus
`TxContextMenuSubmenu` nests child panels to any depth; hovering the trigger row expands one.
:::TuffDemoWrapper{demo="ContextMenuContextMenuSubmenuDemo" code-lang="vue"}
---
code: |
  <template>
    <TxContextMenu>
      <div class="surface">Right-click here</div>

      <template #menu>
        <TxContextMenuItem>Copy</TxContextMenuItem>
        <TxContextMenuSubmenu>
          Share
          <template #menu>
            <TxContextMenuItem>Mail</TxContextMenuItem>
            <TxContextMenuItem>Messages</TxContextMenuItem>
            <TxContextMenuItem>Copy link</TxContextMenuItem>
          </template>
        </TxContextMenuSubmenu>
      </template>
    </TxContextMenu>
  </template>
---
:::

### Best Practices

- For editor shortcuts, command palettes, canvas nodes, and other non-right-click triggers, use `trigger="manual"` with explicit `x` / `y`.
- Keep `anchorMode="pointer"` for real context menus; use `reference` only to align with the whole trigger element.
- Nest menus with `TxContextMenuSubmenu`. If you teleport a `TxContextMenuPanel` yourself, set `outsideGuard` on the child panel.
- Reserve `closeOnSelect=false` for submenu trigger rows and multi-step actions; ordinary commands close on selection.
- Mark destructive actions with `danger`; use `color` only for semantic colors already in the design system.

## API Reference

### TxContextMenu

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `modelValue` | `boolean \| undefined` | `undefined` | Open state (`v-model`); `undefined` leaves it uncontrolled. |
| `x` | `number` | `0` | X coordinate for controlled or manual opening. |
| `y` | `number` | `0` | Y coordinate for controlled or manual opening. |
| `width` | `number` | `220` | Menu width; `0` sizes automatically. |
| `minWidth` | `number` | `0` | Minimum width. |
| `maxWidth` | `number` | `360` | Maximum width; `0` means unlimited. |
| `maxHeight` | `number` | `420` | Maximum height; also shrinks to the available viewport. |
| `unlimitedHeight` | `boolean` | `false` | Removes the height limit. |
| `disabled` | `boolean` | `false` | Blocks triggering and opening. |
| `eager` | `boolean` | `false` | Mounts menu content before the first open. |
| `trigger` | `'contextmenu' \| 'click' \| 'both' \| 'manual'` | `'contextmenu'` | Trigger mode; `manual` opens only through external state and coordinates. |
| `anchorMode` | `'pointer' \| 'reference'` | `'pointer'` | `pointer` follows the pointer or given coordinates; `reference` follows the trigger area. |
| `preventDefault` | `boolean` | `true` | Suppresses the browser's native context menu on right-click. |
| `placement` | `BaseAnchorPlacement` | `'bottom-start'` | Initial placement relative to the anchor point. |
| `offset` | `number` | `2` | Distance from the anchor point. |
| `closeOnEsc` | `boolean` | `true` | Closes on Escape. |
| `closeOnClickOutside` | `boolean` | `true` | Closes on a click outside the menu. |
| `closeOnTriggerPointerDown` | `boolean` | `true` | Closes on a click in the trigger area while open; ignored for `click` / `both`. |
| `closeOnAnyPointerDown` | `boolean` | `false` | Closes on any press outside the menu, including the trigger area. |
| `closeOnSelect` | `boolean` | `true` | Closes after an item is selected. |
| `activationFeedback` | `boolean` | `true` | Clears, then confirms the highlight for 90 ms each before closing; skipped under reduced motion. |
| `showArrow` | `boolean` | `false` | Shows an arrow pointing at the anchor point. |
| `arrowSize` | `number` | `10` | Arrow size. |
| `animation` | `BaseAnchorAnimationOptions` | `{}` | Open and close animation: `transfer`, `boom`, `opacity`, or `none`. |
| `keepAliveContent` | `boolean` | `true` | Keeps content state after closing. |
| `panelVariant` | `'solid' \| 'dashed' \| 'plain'` | `'solid'` | Panel border style. |
| `panelBackground` | `'pure' \| 'mask' \| 'blur' \| 'glass' \| 'refraction'` | `'refraction'` | Panel background effect. |
| `panelShadow` | `'none' \| 'soft' \| 'medium'` | `'medium'` | Panel shadow. |
| `panelRadius` | `number` | `14` | Panel corner radius. |
| `panelPadding` | `number` | `6` | Panel padding. |
| `panelCard` | `BaseAnchorPanelCardProps` | - | Visual props forwarded to the internal `TxCard`. |

#### Events

| Event | Params | Description |
|------|------|------|
| `update:modelValue` | `boolean` | Fires when the open state changes. |
| `open` | `{ x: number; y: number }` | Fires on open with the final coordinates. |
| `close` | - | Fires on close. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `trigger` | - | Trigger element; falls back to the default slot. |
| `default` | - | Trigger content when no `trigger` slot is given. |
| `menu` | - | Menu content, rendered inside the internal `TxContextMenuPanel`. |

#### Exposed Methods

| Name | Type | Description |
|------|------|------|
| `openAt` | `(target?: { x: number; y: number } \| MouseEvent \| PointerEvent) => void` | Opens at a point or at an event's position. |
| `openFromEvent` | `(event: MouseEvent \| PointerEvent) => void` | Opens from a mouse or pointer event. |
| `close` | `() => void` | Closes the menu. |
| `updatePosition` | `() => void` | Recomputes the Floating UI placement. |

### TxContextMenuPanel

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `width` | `number \| string` | - | Panel width. |
| `minWidth` | `number \| string` | - | Minimum width. |
| `maxWidth` | `number \| string` | - | Maximum width. |
| `maxHeight` | `number \| string` | - | Maximum height. |
| `closeOnSelect` | `boolean` | `true` | Whether child items close the panel on selection. |
| `activationFeedback` | `boolean` | `true` | Pre-close confirmation for child items; each item may override it. |
| `close` | `() => void` | - | Close callback injected into child items. |
| `dense` | `boolean` | `false` | Tightens item spacing. |
| `outsideGuard` | `boolean` | `false` | Marks the panel as a menu layer, so clicks inside it aren't outside clicks. |
| `role` | `'menu' \| 'listbox' \| 'none'` | `'menu'` | ARIA role; `menu` / `listbox` enable keyboard navigation, `none` turns it off. |
| `ariaLabel` | `string` | - | Accessible name of the panel. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Items, dividers, or nested overlays. |

#### Exposed Methods

| Name | Type | Description |
|------|------|------|
| `focusFirstItem` | `() => void` | Focuses the first enabled item; call it after opening a standalone panel. |

### TxContextMenuItem

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `disabled` | `boolean` | `false` | Prevents selection. |
| `danger` | `boolean` | `false` | Danger styling. |
| `color` | `string` | - | Label color; CSS variables work. |
| `shortcut` | `string` | - | Shortcut hint on the right. |
| `submenu` | `boolean` | `false` | Shows a submenu arrow. |
| `closeOnSelect` | `boolean` | - | Overrides the parent's `closeOnSelect`. |
| `activationFeedback` | `boolean` | - | Overrides inherited feedback; unset follows the nearest `TxContextMenuPanel`. |

#### Events

| Event | Params | Description |
|------|------|------|
| `select` | - | Fires on selection; a closing item with feedback fires after the 180 ms confirmation. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Main label. |
| `avatar` | - | Leading icon or avatar. |
| `description` | - | Secondary text. |
| `right` | - | Replaces the shortcut and submenu-arrow area. |

### TxContextMenuSubmenu

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `disabled` | `boolean` | `false` | Disables the trigger row; the child panel no longer opens. |
| `placement` | `BaseAnchorPlacement` | `'right-start'` | Child panel position relative to the trigger row. |
| `offset` | `number` | `4` | Distance between the trigger row and the child panel. |
| `width` | `number` | `0` | Fixed child panel width; `0` sizes to content, bounded by `minWidth`. |
| `minWidth` | `number` | `160` | Minimum child panel width. |
| `maxHeight` | `number` | `420` | Maximum child panel height. |
| `unlimitedHeight` | `boolean` | `false` | Removes the child panel's height limit. |
| `animation` | `BaseAnchorAnimationOptions` | `{}` | Child panel animation. |
| `panelCard` | `BaseAnchorPanelCardProps` | - | Card props forwarded to the child panel. |
| `panelVariant` | `'solid' \| 'dashed' \| 'plain'` | `'solid'` | Child panel border style. |
| `panelBackground` | `'pure' \| 'mask' \| 'blur' \| 'glass' \| 'refraction'` | `'refraction'` | Child panel background effect. |
| `panelShadow` | `'none' \| 'soft' \| 'medium'` | `'medium'` | Child panel shadow. |
| `panelRadius` | `number` | `14` | Child panel corner radius. |
| `panelPadding` | `number` | `6` | Child panel padding. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Trigger row label. |
| `right` | - | Trailing info on the trigger row, before the arrow. |
| `menu` | - | Child panel content; may nest another `TxContextMenuSubmenu`. |

### TxContextMenuDivider

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `dashed` | `boolean` | `false` | Dashed separator. |
| `inset` | `boolean` | `false` | Left inset that aligns with items that have icons. |

## Overview

- Placement runs through `TxBaseAnchor` (Floating UI `flip` + `shift` + `size`), flipping, shifting, and shrinking near viewport edges.
- In `pointer` mode, a repeated right-click on the same trigger moves the anchor to the latest position.
- Escape, an outside click, and selection close by default. A closing selection first clears the highlight, confirms with the `TxCardItem` active state, then emits `select`; non-closing items emit at once.
- Submenus inherit the root's `closeOnSelect` and `activationFeedback`, and selecting a child closes the whole chain; clicks inside a child panel aren't outside clicks.
- A hover bridge covers the gap between parent and child panels. Sibling rows crossed on a diagonal don't expand; resting on one for about 100 ms switches to it.
- Keyboard: arrow keys and Home / End move within a panel, counting only `role="menuitem"` (`menu`) or `role="option"` (`listbox`) children; submenus open and close from the keyboard.

## Technologies

- Activation feedback runs on `packages/tuffex/packages/utils/menu-activation-feedback.ts`, shared with DropdownMenu.
- Source: `packages/tuffex/packages/components/src/context-menu/`.

<TuffDocSourceLink />
