ContextMenu
A menu opened by a long press on content, with the content lifted above the backdrop, iOS style.
A long press on a message, a photo or a row opens a menu of actions for that item. The pressed content is lifted above the dimmed screen, so the user sees what the actions apply to.
ContextMenu is Menu with another trigger: Root, Content, Item, Group, Separator and Sub are the same parts.
Installation
npx axiom add context-menupnpm dlx axiom add context-menuyarn dlx axiom add context-menubun x axiom add context-menuAlso copies: menu and its dependencies. context-menu.tsx holds only the trigger: it has no styles, so it’s the same file for every styling variant.
Usage
import { ContextMenu } from "@/components/ui/context-menu";
<ContextMenu.Root>
<ContextMenu.Trigger>
<PhotoThumbnail />
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Item icon="share" onPress={share}>
Share
</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Item icon="trash" destructive onPress={remove}>
Delete
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>;Props
ContextMenu.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
preview | boolean | ReactNode | true | Lifts a copy of the pressed element above the backdrop. Pass a node to show it in the element’s place instead. |
haptic | HapticKind | false | 'medium' | Haptic played when the menu opens. false turns it off. |
asChild | boolean | false | Uses the child as the trigger. |
accessibilityLabel | string | — | Label of the trigger, when its content has no text. |
children | ReactNode | — | The element that opens the menu. |
The other parts and their props are on the Menu page.
Haptics
The menu plays a medium haptic as it opens: it confirms the press was long enough, the way iOS context menus do. Set haptic to change the kind, or false to turn it off. Nothing plays until your app connects a haptics library: see Haptics.
Accessibility
The trigger announces “Long press for options”: screen readers reach the menu through the long press action. Keep the same actions reachable another way too, such as a “more” button or swipe actions.
Use cases
Long press on a message
The message is lifted as a preview above the backdrop; quick reactions sit above it.
<ContextMenu.Root>
<ContextMenu.Trigger>
<MessageBubble message={message} />
</ContextMenu.Trigger>
<ContextMenu.Content>
<Reactions onReact={react} />
<ContextMenu.Item icon="arrow-up" onPress={reply}>
Reply
</ContextMenu.Item>
<ContextMenu.Item icon="copy" onPress={copy}>
Copy
</ContextMenu.Item>
<ContextMenu.Item icon="trash" destructive onPress={remove}>
Delete
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>Row actions in a list
A long press on a row, as an alternative to swipe actions that is easier to discover.
<ContextMenu.Root>
<ContextMenu.Trigger>
<Item onPress={() => open(file)}>…</Item>
</ContextMenu.Trigger>
<ContextMenu.Content>
<ContextMenu.Sub label="Open with…">{apps.map(renderApp)}</ContextMenu.Sub>
<ContextMenu.Item icon="archive" onPress={move}>
Move
</ContextMenu.Item>
<ContextMenu.Item icon="edit" disabled={file.locked} onPress={rename}>
Rename
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>Related
- Menu, opened by a button
- Long press, to open it from a row
- BottomSheet