Navigation

Context Menu

Right-click menu with the same parts and look as Menu, opened at the pointer.

Right-click (or long-press) here

Installation

Install the package (React 19):

terminal
npm install @krackedui/motion

Import the styles once, in your app entry or root layout:

/src/main.tsx
import '@krackedui/motion/styles.css';

Use it anywhere inside your app's <Theme> (see Installation):

/src/ContextMenuExample.tsx
import { useState } from 'react';
import { ContextMenu } from '@krackedui/motion';

export function FileContextMenu() {
  const [pinned, setPinned] = useState(false);
  return (
    <ContextMenu.Root>
      <ContextMenu.Trigger className="flex h-28 w-full max-w-72 items-center justify-center rounded-n-lg text-[14px] text-n-text-secondary shadow-[inset_0_0_0_1px_var(--n-border-primary)]">
        Right-click (or long-press) here
      </ContextMenu.Trigger>
      <ContextMenu.Content width={220}>
        <ContextMenu.Item icon="link" shortcut="⌘L">Copy link</ContextMenu.Item>
        <ContextMenu.Item icon="edit">Rename</ContextMenu.Item>
        <ContextMenu.CheckboxItem checked={pinned} onCheckedChange={setPinned}>Pinned</ContextMenu.CheckboxItem>
        <ContextMenu.Separator />
        <ContextMenu.Item icon="trash" destructive>Delete</ContextMenu.Item>
      </ContextMenu.Content>
    </ContextMenu.Root>
  );
}

Examples

Right-click area

Right-click (or long-press) here

Composition

anatomy.tsx
<ContextMenu.Root>
  <ContextMenu.Trigger>…area…</ContextMenu.Trigger>
  <ContextMenu.Content>
    <ContextMenu.Item />  <ContextMenu.CheckboxItem />  <ContextMenu.RadioGroup />  <ContextMenu.Sub />
  </ContextMenu.Content>
</ContextMenu.Root>
  • Same item parts and props as Menu (Item, CheckboxItem, RadioGroup, RadioItem, ToggleItem, Label, Separator, Group, Sub, SubTrigger, SubContent).

API Reference

ContextMenu.Root

Holds the open state (opened by the pointer, so only onOpenChange).

PropTypeDefault
onOpenChange
(open: boolean) => void
modal
boolean
true

ContextMenu.Trigger

The area that opens the menu.

PropTypeDefault
asChild
boolean
false
disabled
boolean
false

ContextMenu.Content

The floating menu, positioned at the pointer.

PropTypeDefault
width
number
header
ReactNode
footer
ReactNode
side
"top""right""bottom""left"
align
"start""center""end"
collisionPadding
number
8
alignOffset
number
0
loop
boolean
false

ContextMenu.Item

An action row.

PropTypeDefault
icon
IconName | ReactNode
children
ReactNode
description
ReactNode
caption
ReactNode
shortcut
ReactNode
submenu
boolean
false
checked
boolean
false
toggle
boolean
trailing
ReactNode
tone
"default""danger""accent""muted"
"default"
destructive
boolean
false
disabled
boolean
false
onSelect
(event: Event) => void
textValue
string

ContextMenu.CheckboxItem

An on/off option (menuitemcheckbox) with a trailing checkmark when checked.

PropTypeDefault
icon
IconName | ReactNode
children
ReactNode
description
ReactNode
caption
ReactNode
shortcut
ReactNode
checked
boolean | "indeterminate"
onCheckedChange
(checked: boolean) => void
disabled
boolean
false
onSelect
(event: Event) => void
textValue
string

ContextMenu.RadioGroup

Groups RadioItems; exactly one is selected.

PropTypeDefault
value
string
onValueChange
(value: string) => void

ContextMenu.RadioItem

One option of a RadioGroup (menuitemradio), checkmark when selected.

PropTypeDefault
icon
IconName | ReactNode
children
ReactNode
description
ReactNode
caption
ReactNode
shortcut
ReactNode
value
string
disabled
boolean
false
onSelect
(event: Event) => void
textValue
string

ContextMenu.ToggleItem

Motion extra: an on/off row drawn with a switch. Keeps the menu open when toggled.

PropTypeDefault
icon
IconName | ReactNode
children
ReactNode
description
ReactNode
caption
ReactNode
checked
boolean
onCheckedChange
(checked: boolean) => void
disabled
boolean
false
onSelect
(event: Event) => void
textValue
string

ContextMenu.Sub

Wraps a submenu (SubTrigger + SubContent).

PropTypeDefault
open
boolean
defaultOpen
boolean
false
onOpenChange
(open: boolean) => void

ContextMenu.SubTrigger

Row that opens a submenu (→ or Enter opens, ← closes). Draws the chevron itself.

PropTypeDefault
icon
IconName | ReactNode
children
ReactNode
description
ReactNode
caption
ReactNode
disabled
boolean
false
textValue
string

ContextMenu.SubContent

The submenu surface (portalled).

PropTypeDefault
width
number
sideOffset
number
2
collisionPadding
number
8

ContextMenu.Label / Separator / Group

Section label, hairline separator and a grouping wrapper.

PropTypeDefault
className
string

Search: filter field for the header slot (its accessible name defaults to the placeholder). Footer: grey metadata lines for the footer slot.

PropTypeDefault
noIcon
boolean
false
wrapperClassName
string
lines
ReactNode[]
separator
boolean
true

Accessibility

  • Follows the WAI-ARIA menu pattern. Opens on right-click, long-press on touch, or the context menu key / Shift+F10 while the trigger area has focus.
  • Focus moves into the menu; ↑/↓, Home/End, typeahead, Enter/Space, → / ← for submenus, Escape to close.
  • Stays inside the viewport (8px collision padding) and scrolls when it is taller than the space left.
  • Opens and closes with the shared motion layer (styles/motion.css); with prefers-reduced-motion: reduce it only fades.

Usage

  • Use as a shortcut to actions that are also available elsewhere (a Menu button, a toolbar).
  • Don't hide the only way to do something in a context menu: it is invisible until discovered, and harder on touch.
  • Keep it short and in the same order as the matching Menu.
© 2026 Motion. Internal documentation.