Menu

A selectable list in a popover with nested submenus

Features

  • Full keyboard navigation.

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

  • Modal and non-modal modes.

  • Native menus on native platforms.

Installation

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

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

API Reference

Contains every component for the Menu.

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.

  • Required for rendering the menu content.

    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.

  • The menu 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 Menu.

  • Contains the content of the menu.

    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.

  • 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.

  • 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.

    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 and 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.

  • <Menu.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 />
    </Menu.ItemIcon>

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

    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.

  • A component that groups multiple menu items together.

    Props

  • children (required)

    React.ReactNode

    Menu items to group together.

  • A menu item with a checkbox that can be toggled on and 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.

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

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

    Props

  • children

    React.ReactNode

    Custom checkmark icon. Only works on web.

  • forceMount

    true

    Forces the indicator to stay mounted for animation control.

  • 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.

  • Renders an arrow pointing to the trigger.

    Props

  • size

    number | SizeToken

    Width and height of the arrow.

  • unstyled

    boolean

    Removes default arrow styles.

  • Renders a visual divider between menu items. Web only.

    A container for nested submenu components.

    Props

  • children (required)

    React.ReactNode

    SubTrigger, Portal, and SubContent components.

  • open

    boolean

    Controlled open state for the submenu.

  • onOpenChange

    (open: boolean) => void

    Called when the submenu opens or closes.

  • Renders the content of a submenu. Same props as Menu.Content, excluding side and align.

    A menu item that opens a submenu on hover or focus. Accepts the same props as Menu.Item.

    Styling

    Item Highlight Behavior

    Menu items use focusStyle for highlighting rather than hoverStyle. This ensures a unified highlight experience when switching between mouse and keyboard navigation - only one item is ever highlighted at a time.

    When you hover over an item, it receives focus, which triggers the focusStyle. When you use arrow keys to navigate, focus moves to the new item, removing the highlight from the previous one.

    // Default behavior - uses focusStyle for highlight
    <Menu.Item>
    <Menu.ItemTitle>Settings</Menu.ItemTitle>
    </Menu.Item>
    // Custom highlight styling - use focusStyle, not hoverStyle
    <Menu.Item focusStyle={{ backgroundColor: '$blue5' }} >
    <Menu.ItemTitle>Custom Highlight</Menu.ItemTitle>
    </Menu.Item>

    Avoid using hoverStyle for background highlights on Menu.Item. This can cause “double highlighting” when switching between mouse and keyboard - where both the hovered item and the focused item appear highlighted simultaneously.