Context Menu
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.
$ npm add reka-uiAnatomy
Import all parts and piece them together.
<script setup lang="ts">
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuGroup,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'reka-ui'
</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 and uses roving tabindex to manage focus movement among menu items.
Root
Contains all the parts of a context menu.
| Prop | Default | Type | 
|---|---|---|
dir | 'ltr' | 'rtl'The reading direction of the combobox when applicable. If omitted, inherits globally from   | |
modal | true | booleanThe modality of the dropdown menu. When set to   | 
| Emit | Payload | 
|---|---|
update:open | [payload: boolean]Event handler called when the open state of the submenu changes.  | 
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).
| Prop | Default | Type | 
|---|---|---|
as | 'span' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
disabled | false | booleanWhen  Note that this will also restore the native context menu.  | 
| Data Attribute | Value | 
|---|---|
[data-state] | "open" | "closed" | 
Portal
When used, portals the content part into the body.
| Prop | Default | Type | 
|---|---|---|
disabled | booleanDisable teleport and render the component inline  | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.  | |
to | string | HTMLElementVue native teleport component prop   | 
Content
The component that pops out in an open context menu.
| Prop | Default | Type | 
|---|---|---|
alignOffset | 0 | numberAn offset in pixels from the   | 
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
avoidCollisions | true | booleanWhen   | 
collisionBoundary | [] | Element | (Element | null)[] | nullThe element used as the collision boundary. By default this is the viewport, though you can provide additional 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 detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.  | 
disableUpdateOnLayoutShift | booleanWhether to disable the update position for the content when the layout shifted.  | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.  | |
hideWhenDetached | false | booleanWhether to hide the content when the trigger becomes fully occluded.  | 
loop | booleanWhen   | |
positionStrategy | 'fixed' | 'absolute'The type of CSS position property to use.  | |
prioritizePosition | booleanForce content to be position within the viewport. Might overlap the reference element, which may not be desired.  | |
reference | ReferenceElementThe custom element or virtual element that will be set as the reference to position the floating element. If provided, it will replace the default anchor element.  | |
sticky | 'partial' | 'partial' | 'always'The sticky behavior on the align axis.   | 
| Emit | Payload | 
|---|---|
closeAutoFocus | [event: Event]Event handler called when auto-focusing on close. Can be prevented.  | 
escapeKeyDown | [event: KeyboardEvent]Event handler called when the escape key is down. Can be prevented.  | 
focusOutside | [event: FocusOutsideEvent]Event handler called when the focus moves outside of the   | 
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent]Event handler called when an interaction happens outside the   | 
pointerDownOutside | [event: PointerDownOutsideEvent]Event handler called when the a   | 
| Data Attribute | Value | 
|---|---|
[data-state] | "open" | "closed" | 
[data-side] | "left" | "right" | "bottom" | "top" | 
[data-align] | "start" | "end" | "center" | 
| CSS Variable | Description | 
|---|---|
--reka-context-menu-content-transform-origin | 
        The  transform-origin computed from the content and arrow positions/offsets
       | 
--reka-context-menu-content-available-width | 
        The remaining width between the trigger and the boundary edge
        | 
--reka-context-menu-content-available-height | 
        The remaining height between the trigger and the boundary edge
        | 
--reka-context-menu-trigger-width | The width of the trigger  | 
--reka-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.
| Prop | Default | Type | 
|---|---|---|
as | 'svg' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
height | 5 | numberThe height of the arrow in pixels.  | 
rounded | booleanWhen   | |
width | 10 | numberThe width of the arrow in pixels.  | 
Item
The component that contains the context menu items.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
disabled | booleanWhen   | |
textValue | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the   | 
| Emit | Payload | 
|---|---|
select | [event: Event]Event handler called when the user selects an item (via mouse or keyboard).   | 
| Data Attribute | Value | 
|---|---|
[data-highlighted] | Present when highlighted | 
[data-disabled] | Present when disabled | 
Group
Used to group multiple ContextMenu.Items.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | 
Label
Used to render a label. It won't be focusable using arrow keys.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | 
CheckboxItem
An item that can be controlled and rendered like a checkbox.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
disabled | booleanWhen   | |
modelValue | false | true | 'indeterminate'The controlled checked state of the item. Can be used as   | |
textValue | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the   | 
| Emit | Payload | 
|---|---|
select | [event: Event]Event handler called when the user selects an item (via mouse or keyboard).   | 
update:modelValue | [payload: boolean]Event handler called when the value changes.  | 
| Data Attribute | Value | 
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" | 
[data-highlighted] | Present when highlighted | 
[data-disabled] | Present when disabled | 
RadioGroup
Used to group multiple ContextMenu.RadioItems.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
modelValue | stringThe value of the selected item in the group.  | 
| Emit | Payload | 
|---|---|
update:modelValue | [payload: string]Event handler called when the value changes.  | 
RadioItem
An item that can be controlled and rendered like a radio.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
disabled | booleanWhen   | |
textValue | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the   | |
value* | stringThe unique value of the item.  | 
| Emit | Payload | 
|---|---|
select | [event: Event]Event handler called when the user selects an item (via mouse or keyboard).   | 
| 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.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.  | 
| Data Attribute | Value | 
|---|---|
[data-state] | "checked" | "unchecked" | "indeterminate" | 
Separator
Used to visually separate items in the context menu.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | 
Sub
Contains all the parts of a submenu.
| Prop | Default | Type | 
|---|---|---|
defaultOpen | booleanThe open state of the submenu when it is initially rendered. Use when you do not need to control its open state.  | |
open | booleanThe controlled open state of the menu. Can be used as   | 
| Emit | Payload | 
|---|---|
update:open | [payload: boolean]Event handler called when the open state of the submenu changes.  | 
| Slots (default) | Payload | 
|---|---|
open | booleanCurrent open state  | 
SubTrigger
An item that opens a submenu. Must be rendered inside ContextMenu.Sub.
| Prop | Default | Type | 
|---|---|---|
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
disabled | booleanWhen   | |
textValue | stringOptional text used for typeahead purposes. By default the typeahead behavior will use the   | 
| 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.
| Prop | Default | Type | 
|---|---|---|
alignOffset | numberAn offset in pixels from the   | |
arrowPadding | numberThe padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners.  | |
as | 'div' | AsTag | ComponentThe element or component this component should render as. Can be overwritten by   | 
asChild | booleanChange the default rendered element for the one passed as a child, merging their props and behavior. Read our Composition guide for more details.  | |
avoidCollisions | booleanWhen   | |
collisionBoundary | Element | (Element | null)[] | nullThe element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check.  | |
collisionPadding | number | Partial<Record<'top' | 'right' | 'bottom' | 'left', number>>The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }.  | |
disableUpdateOnLayoutShift | booleanWhether to disable the update position for the content when the layout shifted.  | |
forceMount | booleanUsed to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries.  | |
hideWhenDetached | booleanWhether to hide the content when the trigger becomes fully occluded.  | |
loop | booleanWhen   | |
positionStrategy | 'fixed' | 'absolute'The type of CSS position property to use.  | |
prioritizePosition | booleanForce content to be position within the viewport. Might overlap the reference element, which may not be desired.  | |
reference | ReferenceElementThe custom element or virtual element that will be set as the reference to position the floating element. If provided, it will replace the default anchor element.  | |
sideOffset | numberThe distance in pixels from the trigger.  | |
sticky | 'partial' | 'always'The sticky behavior on the align axis.   | |
updatePositionStrategy | 'always' | 'optimized'Strategy to update the position of the floating element on every animation frame.  | 
| Emit | Payload | 
|---|---|
closeAutoFocus | [event: Event]Event handler called when auto-focusing on close. Can be prevented.  | 
entryFocus | [event: Event]Event handler called when container is being focused. Can be prevented.  | 
escapeKeyDown | [event: KeyboardEvent]Event handler called when the escape key is down. Can be prevented.  | 
focusOutside | [event: FocusOutsideEvent]Event handler called when the focus moves outside of the   | 
interactOutside | [event: PointerDownOutsideEvent | FocusOutsideEvent]Event handler called when an interaction happens outside the   | 
openAutoFocus | [event: Event]Event handler called when auto-focusing on open. Can be prevented.  | 
pointerDownOutside | [event: PointerDownOutsideEvent]Event handler called when the a   | 
| Data Attribute | Value | 
|---|---|
[data-state] | "open" | "closed" | 
[data-side] | "left" | "right" | "bottom" | "top" | 
[data-align] | "start" | "end" | "center" | 
| CSS Variable | Description | 
|---|---|
--reka-context-menu-content-transform-origin | 
        The  transform-origin computed from the content and arrow positions/offsets
       | 
--reka-context-menu-content-available-width | The remaining width between the trigger and the boundary edge  | 
--reka-context-menu-content-available-height | The remaining height between the trigger and the boundary edge  | 
--reka-context-menu-trigger-width | The width of the trigger  | 
--reka-context-menu-trigger-height | The height of the trigger  | 
Examples
With submenus
You can create submenus by using ContextMenuSub in combination with its parts.
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuSub,
  ContextMenuSubContent,
  ContextMenuSubTrigger,
  ContextMenuTrigger,
} from 'reka-ui'
</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.
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent>
        <ContextMenuItem
          class="ContextMenuItem"
          disabled
        >
          …
        </ContextMenuItem>
        <ContextMenuItem class="ContextMenuItem">
          …
        </ContextMenuItem>
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>/* styles.css */
.ContextMenuItem[data-disabled] {
  color: gainsboro;
}With separators
Use the Separator part to add a separator between items.
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'reka-ui'
</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.
<script setup lang="ts">
import {
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuLabel,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuTrigger,
} from 'reka-ui'
</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.
<script setup lang="ts">
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuPortal,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'reka-ui'
import { Icon } from '@iconify/vue'
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.
<script setup lang="ts">
import {
  ContextMenuCheckboxItem,
  ContextMenuContent,
  ContextMenuItem,
  ContextMenuItemIndicator,
  ContextMenuPortal,
  ContextMenuRadioGroup,
  ContextMenuRadioItem,
  ContextMenuRoot,
  ContextMenuSeparator,
  ContextMenuTrigger,
} from 'reka-ui'
import { Icon } from '@iconify/vue'
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.
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</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 --reka-context-menu-trigger-width and --reka-context-menu-content-available-height to support this. Use them to constrain the content dimensions.
<script setup lang="ts">
import { ContextMenuContent, ContextMenuItem, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>/* styles.css */
.ContextMenuContent {
  width: var(--reka-context-menu-trigger-width);
  max-height: var(--reka-context-menu-content-available-height);
}Origin-aware animations
We expose a CSS custom property --reka-context-menu-content-transform-origin. Use it to animate the content from its computed origin based on side, sideOffset, align, alignOffset and any collisions.
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>/* styles.css */
.ContextMenuContent {
  transform-origin: var(--reka-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.
<script setup lang="ts">
import { ContextMenuContent, ContextMenuPortal, ContextMenuRoot, ContextMenuTrigger } from 'reka-ui'
</script>
<template>
  <ContextMenuRoot>
    <ContextMenuTrigger>…</ContextMenuTrigger>
    <ContextMenuPortal>
      <ContextMenuContent class="ContextMenuContent">
        …
      </ContextMenuContent>
    </ContextMenuPortal>
  </ContextMenuRoot>
</template>/* 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 to manage focus movement among menu items.
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.  | 
ArrowRightArrowLeft  | 
        
          When focus is on  ContextMenu.SubTrigger, opens or closes
          the submenu depending on reading direction.
        
       | 
Esc  | Closes the context menu  | 
