Skip to content
Docs

Context Menu

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

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

<ContextMenu.root id="context-primitive">
  <ContextMenu.trigger
    id="context-trigger"
    content_id="context-content"
    class="DemoContextMenuTrigger"
  >
    Right-click here.
  </ContextMenu.trigger>
  <ContextMenu.content
    id="context-content"
    class="DemoContextMenuContent"
  >
    <ContextMenu.item
      class="DemoContextMenuItem"
      text_value="Back"
    >
      Back
      <div class="DemoRightSlot">⌘+[</div>
    </ContextMenu.item>
    <ContextMenu.item
      class="DemoContextMenuItem"
      disabled
      text_value="Forward"
    >
      Forward
      <div class="DemoRightSlot">⌘+]</div>
    </ContextMenu.item>
    <ContextMenu.item
      class="DemoContextMenuItem"
      text_value="Reload"
    >
      Reload
      <div class="DemoRightSlot">⌘+R</div>
    </ContextMenu.item>
    <ContextMenu.sub>
      <ContextMenu.sub_trigger
        class="DemoContextMenuSubTrigger"
        text_value="More Tools"
      >
        More Tools
        <div class="DemoRightSlot">
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M6.1584 3.13508C6.35985 2.94621 6.67627 2.95642 6.86514 3.15788L10.61514 7.15788C10.7954 7.3502 10.7954 7.64949 10.61514 7.84182L6.86514 11.8418C6.67627 12.0433 6.35985 12.0535 6.1584 11.8646C5.95694 11.6757 5.94673 11.3593 6.1356 11.1579L9.565 7.49985L6.1356 3.84182C5.94673 3.64036 5.95694 3.32394 6.1584 3.13508Z"
              fill="currentColor"
              fill-rule="evenodd"
              clip-rule="evenodd"
            >
            </path>
          </svg>
        </div>
      </ContextMenu.sub_trigger>
      <ContextMenu.sub_content
        class="DemoContextMenuSubContent"
        side_offset={2}
      >
        <ContextMenu.item
          class="DemoContextMenuItem"
          text_value="Save Page As"
        >
          Save Page As…
          <div class="DemoRightSlot">⌘+S</div>
        </ContextMenu.item>
        <ContextMenu.item
          class="DemoContextMenuItem"
          text_value="Create Shortcut"
        >
          Create Shortcut…
        </ContextMenu.item>
        <ContextMenu.item
          class="DemoContextMenuItem"
          text_value="Name Window"
        >
          Name Window…
        </ContextMenu.item>
        <ContextMenu.separator class="DemoContextMenuSeparator" />
        <ContextMenu.item
          class="DemoContextMenuItem"
          text_value="Developer Tools"
        >
          Developer Tools
        </ContextMenu.item>
      </ContextMenu.sub_content>
    </ContextMenu.sub>

    <ContextMenu.separator class="DemoContextMenuSeparator" />

    <ContextMenu.checkbox_item
      class="DemoContextMenuCheckboxItem"
      checked
      text_value="Show Bookmarks"
    >
      <ContextMenu.item_indicator
        class="DemoContextMenuItemIndicator"
        force_mount
      >
        <svg
          width="15"
          height="15"
          viewBox="0 0 15 15"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
        >
          <path
            d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z"
            fill="currentColor"
            fill-rule="evenodd"
            clip-rule="evenodd"
          >
          </path>
        </svg>
      </ContextMenu.item_indicator>
      Show Bookmarks
      <div class="DemoRightSlot">⌘+B</div>
    </ContextMenu.checkbox_item>
    <ContextMenu.checkbox_item
      class="DemoContextMenuCheckboxItem"
      text_value="Show Full URLs"
    >
      <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">
        <svg
          width="15"
          height="15"
          viewBox="0 0 15 15"
          fill="none"
          xmlns="http://www.w3.org/2000/svg"
          aria-hidden="true"
        >
          <path
            d="M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z"
            fill="currentColor"
            fill-rule="evenodd"
            clip-rule="evenodd"
          >
          </path>
        </svg>
      </ContextMenu.item_indicator>
      Show Full URLs
    </ContextMenu.checkbox_item>

    <ContextMenu.separator class="DemoContextMenuSeparator" />

    <ContextMenu.label class="DemoContextMenuLabel">People</ContextMenu.label>
    <ContextMenu.radio_group value="pedro">
      <ContextMenu.radio_item
        class="DemoContextMenuRadioItem"
        value="pedro"
        checked
      >
        <ContextMenu.item_indicator
          class="DemoContextMenuItemIndicator"
          force_mount
        >
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z"
              fill="currentColor"
            >
            </path>
          </svg>
        </ContextMenu.item_indicator>
        Pedro Duarte
      </ContextMenu.radio_item>
      <ContextMenu.radio_item
        class="DemoContextMenuRadioItem"
        value="colm"
      >
        <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">
          <svg
            width="15"
            height="15"
            viewBox="0 0 15 15"
            fill="none"
            xmlns="http://www.w3.org/2000/svg"
            aria-hidden="true"
          >
            <path
              d="M9.875 7.5C9.875 8.81168 8.81168 9.875 7.5 9.875C6.18832 9.875 5.125 8.81168 5.125 7.5C5.125 6.18832 6.18832 5.125 7.5 5.125C8.81168 5.125 9.875 6.18832 9.875 7.5Z"
              fill="currentColor"
            >
            </path>
          </svg>
        </ContextMenu.item_indicator>
        Colm Tuite
      </ContextMenu.radio_item>
    </ContextMenu.radio_group>
  </ContextMenu.content>
</ContextMenu.root>
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.

Anatomy

Import all parts and piece them together.

<ContextMenu.root id="…">
  <ContextMenu.trigger content_id="…" />
  <ContextMenu.portal>
    <ContextMenu.content id="…">
      <ContextMenu.label />
      <ContextMenu.item />
      <ContextMenu.group>
        <ContextMenu.item />
      </ContextMenu.group>
      <ContextMenu.checkbox_item>
        <ContextMenu.item_indicator />
      </ContextMenu.checkbox_item>
      <ContextMenu.radio_group>
        <ContextMenu.radio_item>
          <ContextMenu.item_indicator />
        </ContextMenu.radio_item>
      </ContextMenu.radio_group>
      <ContextMenu.sub>
        <ContextMenu.sub_trigger />
        <ContextMenu.sub_content />
      </ContextMenu.sub>
      <ContextMenu.separator />
    </ContextMenu.content>
  </ContextMenu.portal>
</ContextMenu.root>

Anatomy

Root
Contains all the parts of a context menu.
Trigger
The area that opens the context menu on right-click or long press.
Portal
Portals the content into the document (default `body`).
Content
The component that pops out in an open context menu.
Item
An actionable menu item.
Checkbox Item
An item that can be checked or unchecked.
Radio Group
Groups mutually exclusive `radio_item` parts.
Radio Item
An item that can be selected among a radio group.
Item Indicator
Renders when a checkbox or radio item is checked.
Label
A non-focusable section label.
Separator
Visually separates groups of items.
Group
Groups multiple items.
Arrow
Optional pointer for submenu positioning.
Sub
Contains all the parts of a submenu.
Sub Trigger
An item that opens a submenu.
Sub Content
The submenu panel.

API Reference

Root

Contains all the parts of a context menu.

Prop Type Default Description
default_open boolean false
dir string "ltr"
id string
modal boolean true
on_open_change string nil
open boolean false
default_open
Type boolean Default false
dir
Type string Default "ltr"
id
Type string Default
modal
Type boolean Default true
on_open_change
Type string Default nil
open
Type boolean Default false

Trigger

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

Prop Type Default Description
content_id string nil
disabled boolean false
id string nil
content_id
Type string Default nil
disabled
Type boolean Default false
id
Type string Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the menu is open.

Portal

When used, portals the content part into the target (default body).

Prop Type Default Description
class any nil
container string "div"
id string
target string "body"
class
Type any Default nil
container
Type string Default "div"
id
Type string Default
target
Type string Default "body"

Content

The component that pops out in an open context menu.

Prop Type Default Description
id string nil
loop boolean true
id
Type string Default nil
loop
Type boolean Default true

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the menu is open.
[data-side] left | right | bottom | top The side the content rendered against.
[data-align] start | end | center The alignment of the content.

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

Item

The component that contains the context menu items.

Prop Type Default Description
disabled boolean false
id string nil
text_value string nil
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Checkbox Item

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

Prop Type Default Description
checked boolean false
disabled boolean false
id string nil
text_value string nil
checked
Type boolean Default false
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the checked state.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Radio Group

Used to group multiple ContextMenu.radio_item parts.

Prop Type Default Description
id string nil
value string nil
id
Type string Default nil
value
Type string Default nil

Radio Item

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

Prop Type Default Description
checked boolean false
disabled boolean false
id string nil
text_value string nil
value string
checked
Type boolean Default false
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil
value
Type string Default

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the selected state.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Item Indicator

Renders when the parent checkbox_item or radio_item is checked.

Prop Type Default Description
force_mount boolean false
id string nil
force_mount
Type boolean Default false
id
Type string Default nil

Data attributes

Attribute Values Description
[data-state] checked | unchecked Reflects the checked state of the parent item.

Label

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

Prop Type Default Description
id string nil
id
Type string Default nil

Separator

Used to visually separate items in the context menu.

Prop Type Default Description
decorative boolean true
id string nil
decorative
Type boolean Default true
id
Type string Default nil

Group

Used to group multiple ContextMenu.item parts.

Prop Type Default Description
id string nil
id
Type string Default nil

Arrow

An optional arrow element rendered alongside a submenu.

Prop Type Default Description
id string nil
id
Type string Default nil

Sub

Contains all the parts of a submenu.

Prop Type Default Description
id string nil
open boolean false
id
Type string Default nil
open
Type boolean Default false

Sub Trigger

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

Prop Type Default Description
disabled boolean false
id string nil
text_value string nil
disabled
Type boolean Default false
id
Type string Default nil
text_value
Type string Default nil

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the submenu is open.
[data-highlighted] Present when highlighted Present when the item is highlighted.
[data-disabled] Present when disabled Present when the item is disabled.

Sub Content

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

Prop Type Default Description
align string "start"
id string nil
side string "right"
side_offset integer 0
align
Type string Default "start"
id
Type string Default nil
side
Type string Default "right"
side_offset
Type integer Default 0

Data attributes

Attribute Values Description
[data-state] open | closed Reflects whether the submenu is open.
[data-side] left | right | bottom | top The side the submenu rendered against.
[data-align] start | end | center The alignment of the submenu.

Examples

With submenus

You can create submenus by using ContextMenu.sub in combination with its parts.

<ContextMenu.root id="context-sub">
  <ContextMenu.trigger id="context-sub-trigger" content_id="context-sub-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-sub-content">
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.separator class="DemoContextMenuSeparator" />
    <ContextMenu.sub>
      <ContextMenu.sub_trigger class="DemoContextMenuSubTrigger">Sub menu →</ContextMenu.sub_trigger>
      <ContextMenu.sub_content class="DemoContextMenuSubContent">
        <ContextMenu.item class="DemoContextMenuItem">Sub menu item</ContextMenu.item>
        <ContextMenu.item class="DemoContextMenuItem">Sub menu item</ContextMenu.item>
        <ContextMenu.arrow class="DemoContextMenuArrow" />
      </ContextMenu.sub_content>
    </ContextMenu.sub>
    <ContextMenu.separator class="DemoContextMenuSeparator" />
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
  </ContextMenu.content>
</ContextMenu.root>

With disabled items

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

<ContextMenu.root id="context-disabled">
  <ContextMenu.trigger id="context-disabled-trigger" content_id="context-disabled-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-disabled-content">
    <ContextMenu.item class="DemoContextMenuItem" disabled>…</ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
  </ContextMenu.content>
</ContextMenu.root>
.DemoContextMenuItem[data-disabled] {
  color: gainsboro;
}

With separators

Use the separator part to add a separator between items.

<ContextMenu.root id="context-separators">
  <ContextMenu.trigger id="context-separators-trigger" content_id="context-separators-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-separators-content">
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.separator class="DemoContextMenuSeparator" />
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.separator class="DemoContextMenuSeparator" />
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
  </ContextMenu.content>
</ContextMenu.root>

With labels

Use the label part to help label a section.

<ContextMenu.root id="context-labels">
  <ContextMenu.trigger id="context-labels-trigger" content_id="context-labels-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-labels-content">
    <ContextMenu.label class="DemoContextMenuLabel">Label</ContextMenu.label>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
  </ContextMenu.content>
</ContextMenu.root>

With checkbox items

Use the checkbox_item part to add an item that can be checked. Pass checked from LiveView assigns to control state.

<ContextMenu.root id="context-checkbox">
  <ContextMenu.trigger id="context-checkbox-trigger" content_id="context-checkbox-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-checkbox-content">
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">…</ContextMenu.item>
    <ContextMenu.separator class="DemoContextMenuSeparator" />
    <ContextMenu.checkbox_item checked={@checked} class="DemoContextMenuCheckboxItem" text_value="Checkbox item">
      <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">✓</ContextMenu.item_indicator>
      Checkbox item
    </ContextMenu.checkbox_item>
  </ContextMenu.content>
</ContextMenu.root>

With radio items

Use the radio_group and radio_item parts to add an item that can be checked amongst others.

<ContextMenu.root id="context-radio">
  <ContextMenu.trigger id="context-radio-trigger" content_id="context-radio-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-radio-content">
    <ContextMenu.radio_group value={@color}>
      <ContextMenu.radio_item value="red" checked={@color == "red"} class="DemoContextMenuRadioItem">
        <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">●</ContextMenu.item_indicator>
        Red
      </ContextMenu.radio_item>
      <ContextMenu.radio_item value="blue" checked={@color == "blue"} class="DemoContextMenuRadioItem">
        <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">●</ContextMenu.item_indicator>
        Blue
      </ContextMenu.radio_item>
      <ContextMenu.radio_item value="green" checked={@color == "green"} class="DemoContextMenuRadioItem">
        <ContextMenu.item_indicator class="DemoContextMenuItemIndicator">●</ContextMenu.item_indicator>
        Green
      </ContextMenu.radio_item>
    </ContextMenu.radio_group>
  </ContextMenu.content>
</ContextMenu.root>

With complex items

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

<ContextMenu.root id="context-complex">
  <ContextMenu.trigger id="context-complex-trigger" content_id="context-complex-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-complex-content">
    <ContextMenu.item class="DemoContextMenuItem">
      <img src="…" alt="" />
      Adolfo Hess
    </ContextMenu.item>
    <ContextMenu.item class="DemoContextMenuItem">
      <img src="…" alt="" />
      Miyah Myles
    </ContextMenu.item>
  </ContextMenu.content>
</ContextMenu.root>

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 width, or constrain its height to not exceed the viewport.

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

<ContextMenu.root id="context-constrain">
  <ContextMenu.trigger id="context-constrain-trigger" content_id="context-constrain-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-constrain-content" class="DemoContextMenuContent">
    …
  </ContextMenu.content>
</ContextMenu.root>
.DemoContextMenuContent {
  width: var(--radix-context-menu-trigger-width);
  max-height: var(--radix-context-menu-content-available-height);
}

Origin-aware animations

We expose a CSS custom property --radix-context-menu-content-transform-origin. Use it to animate the content from its computed origin based on positioning and any collisions.

<ContextMenu.root id="context-origin">
  <ContextMenu.trigger id="context-origin-trigger" content_id="context-origin-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-origin-content" class="DemoContextMenuContent">
    …
  </ContextMenu.content>
</ContextMenu.root>
.DemoContextMenuContent {
  transform-origin: var(--radix-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 change at runtime to reflect collisions. Use them to create collision and direction-aware animations.

<ContextMenu.root id="context-collision">
  <ContextMenu.trigger id="context-collision-trigger" content_id="context-collision-content">…</ContextMenu.trigger>
  <ContextMenu.content id="context-collision-content" class="DemoContextMenuContent">
    …
  </ContextMenu.content>
</ContextMenu.root>
.DemoContextMenuContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.DemoContextMenuContent[data-side="top"] {
  animation-name: slideUp;
}
.DemoContextMenuContent[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

Adheres to the Menu WAI-ARIA design pattern and uses roving tabindex to manage focus movement among menu items.

Keyboard Interactions

Keyboard Interactions

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