Context Menu

A menu component triggered by right-click on web and long press on touch devices

Features

  • Full keyboard navigation.

  • Supports items, icons, images, checkboxes, groups, and more.

  • Supports submenus.

  • Supports modal and non-modal modes.

  • Supports native menus on native platforms.

  • Customizable alignment, offsets, and positioning.

  • Support for native iOS and Android icons.

  • Supports previews on iOS.

Installation

ContextMenu is already installed in tamagui, or you can install it independently:

yarn add @tamagui/context-menu

If you want to use native menus, add these dependencies:

yarn add @react-native-menu/menu
yarn add react-native-ios-context-menu
yarn add react-native-ios-utilities
yarn add zeego

Anatomy

Import all parts and piece them together.

import { ContextMenu } from 'tamagui' // or '@tamagui/context-menu'
export default () => (
<ContextMenu>
<ContextMenu.Trigger asChild>
<YStack>
<Text>Right Click or longPress</Text>
</YStack>
</ContextMenu.Trigger>
<ContextMenu.Portal zIndex={100}>
<ContextMenu.Content>
<ContextMenu.Item>
<ContextMenu.ItemTitle>About Notes</ContextMenu.ItemTitle>
</ContextMenu.Item>
<ContextMenu.Item>
<ContextMenu.ItemTitle>Settings</ContextMenu.ItemTitle>
</ContextMenu.Item>
{/* when title is nested inside a React element then you need to use `textValue` */}
<ContextMenu.Item textValue="Calendar">
<ContextMenu.ItemTitle>
<Text>Calendar</Text>
</ContextMenu.ItemTitle>
<ContextMenu.ItemIcon>
<Calendar color="gray" size="$1" />
</ContextMenu.ItemIcon>
</ContextMenu.Item>
<ContextMenu.Separator />
<ContextMenu.Sub>
<ContextMenu.SubTrigger>
<ContextMenu.ItemTitle>Actions</ContextMenu.ItemTitle>
</ContextMenu.SubTrigger>
<ContextMenu.Portal zIndex={200}>
<ContextMenu.SubContent>
<ContextMenu.Label fontSize={'$1'}>Note settings</ContextMenu.Label>
<ContextMenu.Item onSelect={onSelect} key="create-note">
<ContextMenu.ItemTitle>Create note</ContextMenu.ItemTitle>
</ContextMenu.Item>
<ContextMenu.Item onSelect={onSelect} key="delete-all">
<ContextMenu.ItemTitle>Delete all notes</ContextMenu.ItemTitle>
</ContextMenu.Item>
<ContextMenu.Item onSelect={onSelect} key="sync-all">
<ContextMenu.ItemTitle>Sync notes</ContextMenu.ItemTitle>
</ContextMenu.Item>
</ContextMenu.SubContent>
</ContextMenu.Portal>
</ContextMenu.Sub>
</ContextMenu.Content>
</ContextMenu.Portal>
</ContextMenu>
)

API Reference

ContextMenu

Contains every component for the ContextMenu.

Props

  • children (required)

    React.ReactNode

    Menu parts: Trigger, Portal, Content, Items, etc.

  • placement

    Placement

    Where the menu appears relative to the trigger. Options: 'top' | 'right' | 'bottom' | 'left' with optional '-start' | '-end' alignment.

  • open

    boolean

    Controlled open state for the menu.

  • defaultOpen

    boolean

    Initial open state when uncontrolled.

  • onOpenChange

    (open: boolean) => void

    Called when the menu opens or closes.

  • onOpenWillChange

    (open: boolean) => void

    Called before the open/close animation begins.

  • modal

    boolean

    Default: 

    true

    When true, traps focus inside the menu and blocks outside scroll/interactions.

  • stayInFrame

    ShiftProps | boolean

    Shifts the menu to stay within viewport bounds.

  • allowFlip

    FlipProps | boolean

    Flips the menu to the opposite side if there is insufficient space.

  • offset

    OffsetOptions

    Distance between the menu and its trigger.

  • unstyled

    boolean

    Removes all default Tamagui styles.

  • ContextMenu.Portal

    This is necessary for the ContextMenu.

    Props

  • zIndex

    number

    Stacking order of the portal layer.

  • children (required)

    React.ReactNode

    Content to render inside the portal.

  • forceMount

    true

    Forces the portal to stay mounted, useful for controlling animations.

  • ContextMenu.Trigger

    The ContextMenu will only be triggered when the user right-clicks or long-presses within the Trigger area.

    Props

  • action

    press|longPress

    Default: 

    longPress

    Works with the native prop and accepts 'press' or 'longPress'. The default is 'longPress' for ContextMenu.

  • ContextMenu.Content

    Contains the content of the ContextMenu.

    Props

  • children (required)

    React.ReactNode

    Menu items, groups, labels, separators, and submenus.

  • loop

    boolean

    Default: 

    false

    Whether keyboard navigation wraps from last to first item.

  • forceMount

    true

    Forces the content to stay mounted, useful for controlling animations.

  • onCloseAutoFocus

    (event: Event) => void

    Called when focus returns to the trigger after closing.

  • onEscapeKeyDown

    (event: KeyboardEvent) => void

    Called when the escape key is pressed. Can be prevented.

  • onPointerDownOutside

    (event: PointerEvent) => void

    Called when a pointer event occurs outside the content.

  • onInteractOutside

    (event: Event) => void

    Called when any interaction occurs outside the content.

  • ContextMenu.Item

    A selectable menu item that triggers an action when selected.

    Props

  • key (required)

    string

    Unique identifier for the item.

  • disabled

    boolean

    Default: 

    false

    Prevents interaction and dims the item.

  • destructive

    boolean

    Renders the item in red on iOS to indicate a dangerous action (e.g. delete). No effect on web.

  • hidden

    boolean

    Hides the item from the menu.

  • onSelect

    (event?: Event) => void

    Called when the item is selected via click or keyboard.

  • onFocus

    () => void

    Called when the item receives focus.

  • onBlur

    () => void

    Called when the item loses focus.

  • textValue

    string

    Text used for typeahead and native menus. Required when ItemTitle contains a React node instead of a string.

  • ContextMenu.ItemTitle

    Renders the title of the menu item.

    Props

  • children (required)

    string | React.ReactNode

    The title text or element to display.

  • You can directly pass a text node to the ItemTitle. However, if you use a nested React node like <Text>, you need to pass textValue to the <Item> so that it works with native menus.

    ContextMenu.ItemIcon

    A component to render an icon. For non-native menus, you can pass an icon component. For native menus, you can pass platform-specific icons to the android/ios props.

    On iOS, it renders the native SF Symbols  icons.

    Props

  • children

    React.ReactNode

    Fallback icon for web when native icons are not available.

  • ios

    object

    SF Symbol configuration: name, weight, scale, hierarchicalColor, paletteColors.

  • android

    object

    Android resource drawable name.

  • <ContextMenu.ItemIcon ios={{ name: '0.circle.fill', // required pointSize: 5, weight: 'semibold', scale: 'medium', // can also be a color string. Requires iOS 15+ hierarchicalColor: { dark: 'blue', light: 'green', }, // alternative to hierarchical color. Requires iOS 15+ paletteColors: [ { dark: 'blue', light: 'green', }, ], }} >
    <CircleIcon />
    </ContextMenu.ItemIcon>

    ContextMenu.ItemImage

    A component to render an item image. For native menus, it only works on iOS. It takes the same properties as @tamagui/image.

    ContextMenu.ItemSubtitle

    A component to render a subtitle for the menu item. For native menus, it only works on iOS.

    Props

  • children (required)

    string

    The subtitle text to display below the title.

  • ContextMenu.Group

    A component that groups multiple menu items together.

    Props

  • children (required)

    React.ReactNode

    Menu items to group together.

  • ContextMenu.CheckboxItem

    A menu item with a checkbox that can be toggled on/off.

    Props

  • key (required)

    string

    Unique identifier for the checkbox item.

  • disabled

    boolean

    Default: 

    false

    Prevents interaction and dims the item.

  • destructive

    boolean

    Renders the item in red on iOS to indicate a dangerous action. No effect on web.

  • hidden

    boolean

    Hides the item from the menu.

  • onFocus

    () => void

    Called when the item receives focus.

  • onBlur

    () => void

    Called when the item loses focus.

  • textValue

    string

    Text for native menus. Required when ItemTitle contains a React node.

  • value

    'on' | 'off' | 'mixed'

    Controlled checked state for native menus.

  • onValueChange

    (state, prevState) => void

    Called when checked state changes on native menus.

  • checked

    boolean

    Controlled checked state for web menus.

  • onCheckedChange

    (checked: boolean) => void

    Called when checked state changes on web.

  • ContextMenu.ItemIndicator

    Use inside CheckboxItem or RadioItem to indicate when an item is checked. This allows you to conditionally render a checkmark.

    <ContextMenu.ItemIndicator>
    <CheckmarkIcon /> {/* This does not work with the native prop. */}
    </ContextMenu.ItemIndicator>

    Props

  • children

    React.ReactNode

    Custom checkmark icon. Only works on web.

  • forceMount

    true

    Forces the indicator to stay mounted for animation control.

  • ContextMenu.Label

    Renders a non-focusable label for a group of items. On native menus, only one label is supported per menu and submenu.

    Props

  • children (required)

    string

    The label text.

  • textValue

    string

    Text for native menus when children is a React node.

  • ContextMenu.Arrow

    Renders an arrow pointing to the trigger.

    Props

  • size

    number | SizeToken

    Width and height of the arrow.

  • unstyled

    boolean

    Removes default arrow styles.

  • ContextMenu.Separator

    Renders a visual divider between menu items. Web only.

    ContextMenu.Sub

    A container for nested sub-menu components.

    Props

  • children (required)

    React.ReactNode

    SubTrigger, Portal, and SubContent components.

  • open

    boolean

    Controlled open state for the sub-menu.

  • onOpenChange

    (open: boolean) => void

    Called when the sub-menu opens or closes.

  • ContextMenu.SubContent

    Renders the content of a sub-menu. Same props as Content, excluding side and align.

    ContextMenu.SubTrigger

    A menu item that opens a sub-menu on hover/focus. Accepts the same props as Item.

    ContextMenu.Preview

    When the ContextMenu is visible, this renders a custom preview component. Only works with native iOS menus.

    Should be rendered as a child of ContextMenu.Content.

    Props

  • children (required)

    React.ReactNode | (() => React.ReactNode)

    The preview content to render. Can be a function for lazy rendering.

  • size

    { width?: number, height?: number }

    Dimensions of the preview.

  • onPress

    () => void

    Called when the preview is pressed.

  • backgroundColor

    string | { dark: string, light: string }

    Background color of the preview.

  • borderRadius

    number

    Border radius of the preview.

  • preferredCommitStyle

    'pop' | 'dismiss'

    Default: 

    'dismiss'

    Exit transition when preview is tapped. Use 'pop' when navigating to another screen.

  • <ContextMenu.Preview // optional props: preferredCommitStyle="pop" // or "dismiss" backgroundColor={{ // or a color string directly dark: 'black', light: 'white', }} >
    {() => <Preview />}
    </ContextMenu.Preview>