---
title: "Context Menu"
description: "Displays a menu located at the pointer, triggered by a right-click or a long-press."
canonical_url: "https://vinicunca.dev/akar/components/context-menu"
---
# Context Menu

> Displays a menu located at the pointer, triggered by a right-click or a long-press.

```vue [index.vue]
<script setup lang="ts">
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'akar'
import { ref } from 'vue'
import './styles.css'

const checkboxOne = ref(false)
const checkboxTwo = ref(false)
const person = ref('pedro')

function handleClick() {
  // eslint-disable-next-line no-alert
  alert('hello!')
}
</script>

<template>
  <div class="akar-demo akar-demo-ContextMenu">
    <ContextMenuRoot>
        <ContextMenuTrigger
          as-child
          class="ContextMenuTrigger"
        >
          <span> Right click here. </span>
        </ContextMenuTrigger>
        <ContextMenuPortal>
          <ContextMenuContent
            class="ContextMenuContent"
            :side-offset="5"
          >
            <ContextMenuItem
              value="New Tab"
              class="ContextMenuItem"
              @click="handleClick"
            >
              New Tab <div
                class="RightSlot"
              >
                ⌘+T
              </div>
            </ContextMenuItem>
            <ContextMenuSub>
              <ContextMenuSubTrigger
                value="more toolsz"
                class="ContextMenuSubTrigger"
              >
                More Tools <div
                  class="RightSlot"
                >
                  <PIcon name="i-lucide-chevron-right" />
                </div>
              </ContextMenuSubTrigger>
              <ContextMenuPortal>
                <ContextMenuSubContent
                  class="ContextMenuSubContent"
                  :side-offset="2"
                  :align-offset="-5"
                >
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Save Page As… <div
                      class="RightSlot"
                    >
                      ⌘+S
                    </div>
                  </ContextMenuItem>
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Create Shortcut…
                  </ContextMenuItem>
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Name Window…
                  </ContextMenuItem>
                  <ContextMenuSeparator class="ContextMenuSeparator" />
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Developer Tools
                  </ContextMenuItem>
                </ContextMenuSubContent>
              </ContextMenuPortal>
            </ContextMenuSub>
            <ContextMenuItem
              value="New Window"
              class="ContextMenuItem"
            >
              New Window <div
                class="RightSlot"
              >
                ⌘+N
              </div>
            </ContextMenuItem>
            <ContextMenuItem
              value="New Private Window"
              class="ContextMenuItem"
              disabled
            >
              New Private Window <div
                class="RightSlot"
              >
                ⇧+⌘+N
              </div>
            </ContextMenuItem>
            <ContextMenuSub>
              <ContextMenuSubTrigger
                value="more tools"
                class="ContextMenuSubTrigger"
              >
                More Tools <div
                  class="RightSlot"
                >
                  <PIcon name="i-lucide-chevron-right" />
                </div>
              </ContextMenuSubTrigger>
              <ContextMenuPortal>
                <ContextMenuSubContent
                  class="ContextMenuSubContent"
                  :side-offset="2"
                  :align-offset="-5"
                >
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Save Page As… <div
                      class="RightSlot"
                    >
                      ⌘+S
                    </div>
                  </ContextMenuItem>
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Create Shortcut…
                  </ContextMenuItem>
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Name Window…
                  </ContextMenuItem>
                  <ContextMenuSeparator class="ContextMenuSeparator" />
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Developer Tools
                  </ContextMenuItem>
                  <ContextMenuSub>
                    <ContextMenuSubTrigger
                      value="more toolsz"
                      class="ContextMenuSubTrigger"
                    >
                      More Tools <div
                        class="RightSlot"
                      >
                        <PIcon name="i-lucide-chevron-right" />
                      </div>
                    </ContextMenuSubTrigger>
                    <ContextMenuPortal>
                      <ContextMenuSubContent
                        class="ContextMenuSubContent"
                        :side-offset="2"
                        :align-offset="-5"
                      >
                        <ContextMenuItem
                          class="ContextMenuItem"
                        >
                          Save Page As… <div
                            class="RightSlot"
                          >
                            ⌘+S
                          </div>
                        </ContextMenuItem>
                        <ContextMenuItem
                          class="ContextMenuItem"
                        >
                          Create Shortcut…
                        </ContextMenuItem>
                        <ContextMenuItem
                          class="ContextMenuItem"
                        >
                          Name Window…
                        </ContextMenuItem>
                        <ContextMenuSeparator class="ContextMenuSeparator" />
                        <ContextMenuItem
                          class="ContextMenuItem"
                        >
                          Developer Tools
                        </ContextMenuItem>
                        <ContextMenuSub>
                          <ContextMenuSubTrigger
                            value="more toolsz"
                            class="ContextMenuSubTrigger"
                          >
                            More Tools <div
                              class="RightSlot"
                            >
                              <PIcon name="i-lucide-chevron-right" />
                            </div>
                          </ContextMenuSubTrigger>
                          <ContextMenuPortal>
                            <ContextMenuSubContent
                              class="ContextMenuSubContent"
                              :side-offset="2"
                              :align-offset="-5"
                            >
                              <ContextMenuItem
                                class="ContextMenuItem"
                              >
                                Save Page As… <div
                                  class="RightSlot"
                                >
                                  ⌘+S
                                </div>
                              </ContextMenuItem>
                              <ContextMenuItem
                                class="ContextMenuItem"
                              >
                                Create Shortcut…
                              </ContextMenuItem>
                              <ContextMenuItem
                                class="ContextMenuItem"
                              >
                                Name Window…
                              </ContextMenuItem>
                              <ContextMenuSeparator class="ContextMenuSeparator" />
                              <ContextMenuItem
                                class="ContextMenuItem"
                              >
                                Developer Tools
                              </ContextMenuItem>
                            </ContextMenuSubContent>
                          </ContextMenuPortal>
                        </ContextMenuSub>
                      </ContextMenuSubContent>
                    </ContextMenuPortal>
                  </ContextMenuSub>
                  <ContextMenuItem
                    class="ContextMenuItem"
                  >
                    Developer Tools
                  </ContextMenuItem>
                </ContextMenuSubContent>
              </ContextMenuPortal>
            </ContextMenuSub>
            <ContextMenuSeparator class="ContextMenuSeparator" />
            <ContextMenuCheckboxItem
              v-model="checkboxOne"
              class="ContextMenuItem"
            >
              <ContextMenuItemIndicator class="ContextMenuItemIndicator">
                <PIcon name="i-lucide-check" />
              </ContextMenuItemIndicator> Show Bookmarks <div
                class="RightSlot"
              >
                ⌘+B
              </div>
            </ContextMenuCheckboxItem>
            <ContextMenuCheckboxItem
              v-model="checkboxTwo"
              class="ContextMenuItem"
            >
              <ContextMenuItemIndicator class="ContextMenuItemIndicator">
                <PIcon name="i-lucide-check" />
              </ContextMenuItemIndicator> Show Full URLs
            </ContextMenuCheckboxItem>
            <ContextMenuSeparator class="ContextMenuSeparator" />
            <ContextMenuLabel class="ContextMenuLabel">
              People
            </ContextMenuLabel>
            <ContextMenuRadioGroup v-model="person">
              <ContextMenuRadioItem
                class="ContextMenuItem"
                value="pedro"
              >
                <ContextMenuItemIndicator class="ContextMenuItemIndicator">
                  <PIcon name="i-lucide-circle" />
                </ContextMenuItemIndicator> Pedro Duarte
              </ContextMenuRadioItem>
              <ContextMenuRadioItem
                class="ContextMenuItem"
                value="colm"
              >
                <ContextMenuItemIndicator class="ContextMenuItemIndicator">
                  <PIcon name="i-lucide-circle" />
                </ContextMenuItemIndicator> Colm Tuite
              </ContextMenuRadioItem>
            </ContextMenuRadioGroup>
          </ContextMenuContent>
        </ContextMenuPortal>
      </ContextMenuRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';

@scope (.akar-demo-ContextMenu) {
.ContextMenuTrigger {
  display: block;
  border: 2px white dashed;
  color: white;
  border-radius: 4px;
  font-size: 15px;
  user-select: none;
  padding: 45px 0;
  width: 300px;
  text-align: center;
}

.ContextMenuContent,
.ContextMenuSubContent {
  min-width: 220px;
  background-color: white;
  border-radius: 6px;
  overflow: hidden;
  padding: 5px;
  box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
}

.ContextMenuItem,
.ContextMenuCheckboxItem,
.ContextMenuRadioItem,
.ContextMenuSubTrigger {
  font-size: 13px;
  line-height: 1;
  color: var(--grass-11);
  border-radius: 3px;
  display: flex;
  align-items: center;
  height: 25px;
  padding: 0 5px;
  position: relative;
  padding-left: 25px;
  user-select: none;
  outline: none;
}
.ContextMenuSubTrigger[data-state='open'] {
  background-color: var(--grass-4);
  color: var(--grass-11);
}
.ContextMenuItem[data-disabled],
.ContextMenuCheckboxItem[data-disabled],
.ContextMenuRadioItem[data-disabled],
.ContextMenuSubTrigger[data-disabled] {
  color: var(--mauve-8);
  pointer-events: 'none';
}
.ContextMenuItem[data-highlighted],
.ContextMenuCheckboxItem[data-highlighted],
.ContextMenuRadioItem[data-highlighted],
.ContextMenuSubTrigger[data-highlighted] {
  background-color: var(--grass-9);
  color: var(--grass-1);
}

.ContextMenuLabel {
  padding-left: 25px;
  font-size: 12px;
  line-height: 25px;
  color: var(--mauve-11);
}

.ContextMenuSeparator {
  height: 1px;
  background-color: var(--grass-6);
  margin: 5px;
}

.ContextMenuItemIndicator {
  position: absolute;
  left: 0;
  width: 25px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.RightSlot {
  margin-left: auto;
  padding-left: 20px;
  color: var(--mauve-11);
}
[data-highlighted] > .RightSlot {
  color: white;
}
[data-disabled] .RightSlot {
  color: var(--mauve-8);
}
}
```

## Features

- Supports submenus with configurable reading direction.
- Supports items, labels, groups of items.
- Supports checkable items (single or multiple) with optional indeterminate state.
- Supports modal and non-modal modes.
- Customize side, alignment, offsets, collision handling.
- Focus is fully managed.
- Full keyboard navigation.
- Typeahead support.
- Dismissing and layering behavior is highly customizable.
- Triggers with a long-press on touch devices

## Installation

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup lang="ts">
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'akar';
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger />

    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuLabel />
        <ContextMenuItem />

        <ContextMenuGroup>
          <ContextMenuItem />
        </ContextMenuGroup>

        <ContextMenuCheckboxItem>
          <ContextMenuItemIndicator />
        </ContextMenuCheckboxItem>

        <ContextMenuRadioGroup>
          <ContextMenuRadioItem>
            <ContextMenuItemIndicator />
          </ContextMenuRadioItem>
        </ContextMenuRadioGroup>

        <ContextMenuSub>
          <ContextMenuSubTrigger />
          <ContextMenuPortal>
            <ContextMenuSubContent />
          </ContextMenuPortal>
        </ContextMenuSub>

        <ContextMenuSeparator />
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

## API Reference

Adheres to the [Menu WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu) and uses [roving tabindex](https://www.w3.org/TR/wai-aria-practices-1.2/examples/menu-button/menu-button-actions.html) to manage focus movement among menu items.

### Root

Contains all the parts of a context menu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `modal` | `true` | `boolean` | The modality of the dropdown menu.<br><br>When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. |
| `pressOpenDelay` | `700` | `number` | The duration from when the trigger is pressed until the menu opens. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `payload: boolean` |  |

[ContextMenuRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRoot.vue)

### Trigger

The area that opens the context menu. Wrap it around the target you want the context menu to open from when right-clicking (or using the relevant keyboard shortcuts).

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` | `false` | `boolean` | When `true`, the context menu would not open when right-clicking.<br><br>Note that this will also restore the native context menu. |

[ContextMenuTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |

### Portal

When used, portals the content part into the `body`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defer` |  | `boolean` | Defer the resolving of a Teleport target until other parts of the<br>application have mounted (requires Vue 3.5.0+)<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) |
| `disabled` |  | `boolean` | Disable teleport and render the component inline<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `to` |  | `string \| HTMLElement` | Vue native teleport component prop `:to`<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) |

[ContextMenuPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuPortal.vue)

### Content

The component that pops out in an open context menu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.<br>May only occur when `prioritizePosition` is true. |
| `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences<br>to prevent collisions with boundary edges. |
| `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default<br>this is the viewport, though you can provide additional<br>element(s) to be included in this check. |
| `collisionPadding` | `0` | `number \| Partial<Record<"top" \| "right" \| "bottom" \| "left", number>>` | The distance in pixels from the boundary edges where collision<br>detection should occur. Accepts a number (same for all sides),<br>or a partial padding object, for example: { top: 20, left: 20 }. |
| `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered<br>to the reference element. |
| `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. |
| `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
| `memoDependencies` |  | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. |
| `positionStrategy` |  | `"fixed" \| "absolute"` | The type of CSS position property to use. |
| `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` |  | `ReferenceElement` | The custom element or virtual element that will be set as the reference<br>to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. |
| `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the<br>content in the boundary as long as the trigger is at least partially<br>in the boundary whilst "always" will keep the content in the boundary<br>regardless. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.<br>Can be prevented. |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `openAutoFocus` | `event: Event` |  |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[ContextMenuContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" |
| `[data-align]` | "start" \\| "end" \\| "center" |

| CSS variable | Description |
| --- | --- |
| `--akar-context-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--akar-context-menu-content-available-width` | The remaining width between the trigger and the boundary edge |
| `--akar-context-menu-content-available-height` | The remaining height between the trigger and the boundary edge |
| `--akar-context-menu-trigger-width` | The width of the trigger |
| `--akar-context-menu-trigger-height` | The height of the trigger |

### Arrow

An optional arrow element to render alongside a submenu. This can be used to help visually link the trigger item with the `ContextMenu.Content`. Must be rendered inside `ContextMenu.Content`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `height` | `5` | `number` | The height of the arrow in pixels. |
| `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` |
| `width` | `10` | `number` | The width of the arrow in pixels. |

[ContextMenuArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuArrow.vue)

### Item

The component that contains the context menu items.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |

[ContextMenuItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### Group

Used to group multiple `ContextMenu.Item`s.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ContextMenuGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuGroup.vue)

### Label

Used to render a label. It won't be focusable using arrow keys.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ContextMenuLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuLabel.vue)

### CheckboxItem

An item that can be controlled and rendered like a checkbox.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `modelValue` |  | `false \| true \| "indeterminate"` | The controlled checked state of the item. Can be used as `v-model`. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |
| `update:modelValue` | `payload: boolean` | Event handler called when the checked state changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `checked` | `false \| true \| "indeterminate"` | Current checked state |
| `modelValue` | `CheckedState` | Current modelValue state |

[ContextMenuCheckboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuCheckboxItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### RadioGroup

Used to group multiple `ContextMenu.RadioItem`s.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `modelValue` |  | `AcceptableValue` | The value of the selected item in the group. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `payload: AcceptableValue` | Event handler called when the value changes. |

[ContextMenuRadioGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRadioGroup.vue)

### RadioItem

An item that can be controlled and rendered like a radio.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |
| `value*` |  | `AcceptableValue` | The unique value of the item. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `checked` | `boolean` | Current checked state |

[ContextMenuRadioItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuRadioItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### ItemIndicator

Renders when the parent `ContextMenu.CheckboxItem` or `ContextMenu.RadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |

[ContextMenuItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuItemIndicator.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |

### Separator

Used to visually separate items in the context menu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ContextMenuSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSeparator.vue)

### Sub

Contains all the parts of a submenu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defaultOpen` |  | `boolean` | The open state of the submenu when it is initially rendered. Use when you do not need to control its open state. |
| `open` |  | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `payload: boolean` | Event handler called when the open state of the submenu changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `open` | `boolean` | Current open state |

[ContextMenuSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSub.vue)

### SubTrigger

An item that opens a submenu. Must be rendered inside `ContextMenu.Sub`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `graceDuration` | `300` | `number` | Time in milliseconds to keep a submenu open while the pointer moves from<br>its trigger to the submenu. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

[ContextMenuSubTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSubTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### SubContent

The component that pops out when a submenu is open. Must be rendered inside `ContextMenu.Sub`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.<br>May only occur when `prioritizePosition` is true. |
| `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. |
| `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.<br>If your content has border-radius, this will prevent it from<br>overflowing the corners. |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences<br>to prevent collisions with boundary edges. |
| `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default<br>this is the viewport, though you can provide additional<br>element(s) to be included in this check. |
| `collisionPadding` | `0` | `number \| Partial<Record<"top" \| "right" \| "bottom" \| "left", number>>` | The distance in pixels from the boundary edges where collision<br>detection should occur. Accepts a number (same for all sides),<br>or a partial padding object, for example: { top: 20, left: 20 }. |
| `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered<br>to the reference element. |
| `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. |
| `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
| `memoDependencies` |  | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. |
| `positionStrategy` |  | `"fixed" \| "absolute"` | The type of CSS position property to use. |
| `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` |  | `ReferenceElement` | The custom element or virtual element that will be set as the reference<br>to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. |
| `sideOffset` | `0` | `number` | The distance in pixels from the trigger. |
| `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the<br>content in the boundary as long as the trigger is at least partially<br>in the boundary whilst "always" will keep the content in the boundary<br>regardless. |
| `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.<br>Can be prevented. |
| `entryFocus` | `event: Event` |  |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `openAutoFocus` | `event: Event` |  |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[ContextMenuSubContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu/ContextMenuSubContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" |
| `[data-align]` | "start" \\| "end" \\| "center" |

| CSS variable | Description |
| --- | --- |
| `--akar-context-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--akar-context-menu-content-available-width` | The remaining width between the trigger and the boundary edge |
| `--akar-context-menu-content-available-height` | The remaining height between the trigger and the boundary edge |
| `--akar-context-menu-trigger-width` | The width of the trigger |
| `--akar-context-menu-trigger-height` | The height of the trigger |

## Examples

### With submenus

You can create submenus by using `ContextMenuSub` in combination with its parts.

```vue
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuSub>
          <ContextMenuSubTrigger>Sub menu →</ContextMenuSubTrigger>
          <ContextMenuPortal>
            <ContextMenuSubContent>
              <ContextMenuItem>Sub menu item</ContextMenuItem>
              <ContextMenuItem>Sub menu item</ContextMenuItem>
              <ContextMenuArrow />
            </ContextMenuSubContent>
          </ContextMenuPortal>
        </ContextMenuSub>
        <ContextMenuSeparator />
        <ContextMenuItem>…</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### With disabled items

You can add special styles to disabled items via the `data-disabled` attribute.

```vue
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem
          class="ContextMenuItem"
          disabled
        >
          …
        </ContextMenuItem>
        <ContextMenuItem class="ContextMenuItem">
          …
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

```css
/* styles.css */
.ContextMenuItem[data-disabled] {
  color: gainsboro;
}
```

### With separators

Use the `Separator` part to add a separator between items.

```vue
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuItem>…</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### With labels

Use the `Label` part to help label a section.

```vue
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuTrigger,
} from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuLabel>Label</ContextMenuLabel>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuItem>…</ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### With checkbox items

Use the `CheckboxItem` part to add an item that can be checked.

```vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'akar'

const checked = ref(true)
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuItem>…</ContextMenuItem>
        <ContextMenuSeparator />
        <ContextMenuCheckboxItem v-model="checked">
          <ContextMenuItemIndicator>
            <Icon icon="radix-icons:check" />
          </ContextMenuItemIndicator>
          Checkbox item
        </ContextMenuCheckboxItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### With radio items

Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others.

```vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'akar'

const color = ref('blue')
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuRadioGroup v-model="color">
          <ContextMenuRadioItem value="red">
            <ContextMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </ContextMenuItemIndicator>
            Red
          </ContextMenuRadioItem>
          <ContextMenuRadioItem value="blue">
            <ContextMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </ContextMenuItemIndicator>
            Blue
          </ContextMenuRadioItem>
          <ContextMenuRadioItem value="green">
            <ContextMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </ContextMenuItemIndicator>
            Green
          </ContextMenuRadioItem>
        </ContextMenuRadioGroup>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### With complex items

You can add extra decorative elements in the `Item` parts, such as images.

```vue
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem>
          <img src="…">
          Adolfo Hess
        </ContextMenuItem>
        <ContextMenuItem>
          <img src="…">
          Miyah Myles
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

### Constrain the content/sub-content size

You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport.

We expose several CSS custom properties such as `--akar-context-menu-trigger-width` and `--akar-context-menu-content-available-height` to support this. Use them to constrain the content dimensions.

```vue
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

```css
/* styles.css */
.ContextMenuContent {
  width: var(--akar-context-menu-trigger-width);
  max-height: var(--akar-context-menu-content-available-height);
}
```

### Origin-aware animations

We expose a CSS custom property `--akar-context-menu-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions.

```vue
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

```css
/* styles.css */
.ContextMenuContent {
  transform-origin: var(--akar-context-menu-content-transform-origin);
  animation: scaleIn 0.5s ease-out;
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
```

### Collision-aware animations

We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations.

```vue
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'akar'
</script>

<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>
```

```css
/* styles.css */
.ContextMenuContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.ContextMenuContent[data-side="top"] {
  animation-name: slideUp;
}
.ContextMenuContent[data-side="bottom"] {
  animation-name: slideDown;
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
```

## Accessibility

Uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/patterns/kbd_roving_tabindex) to manage focus movement among menu items.

### Keyboard Interactions

| Key | Description |
| --- | --- |
| <kbd>Space</kbd> | Activates the focused item. |
| <kbd>Enter</kbd> | Activates the focused item. |
| <kbd>ArrowDown</kbd> | Moves focus to the next item. |
| <kbd>ArrowUp</kbd> | Moves focus to the previous item. |
| <kbd>ArrowRight</kbd> / <kbd>ArrowLeft</kbd> |  When focus is on `ContextMenu.SubTrigger`, opens or closes the submenu depending on reading direction.  |
| <kbd>Esc</kbd> | Closes the context menu |

---

- [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/menu)
- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/ContextMenu)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
