Menu
A selectable list in a popover with nested submenus
Menu presents keyboard-navigable actions, selections, groups, and submenus in a popover or platform-native menu.
Features
Full keyboard navigation
Submenus, items, icons, images, checkboxes, and groups
Modal and non-modal modes
Platform-native menus on mobile
Menu displays a list of actions or options in a floating panel triggered by a button. It supports nested submenus, keyboard navigation, native platform menus, and automatically stacks above other content.
Installation
Menu is already installed in tamagui, or you can install it independently:
yarn
npm
bun
pnpm
For Expo 57 and React Native 0.86, use the Expo UI adapter:
yarn
npm
bun
pnpm
Then add the setup import at your app entry point:
The Zeego adapter remains available for apps on compatible React Native versions:
yarn
npm
bun
pnpm
On native, Menu.Trigger coordinates with parent Tamagui pressables
automatically. You should not need extra wrapper views or empty onPress
handlers just to prevent a parent press: clause from activating.
Expo Router users: This import must run before expo-router/entry. Create an index.js at your project root that imports the setup first, then expo-router, and update your package.json main field to "index.js". See the Expo guide for details.
Anatomy
Import all parts and piece them together.
API reference
Menu
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:
trueWhen true, traps focus inside the menu and blocks outside scroll/interactions.
stayInFrame
ShiftProps | boolean
Default:
{ padding: 10 }Shifts the menu horizontally to stay within viewport bounds. Pass an object to customize shift behavior (mainAxis, crossAxis, padding).
allowFlip
FlipProps | boolean
Default:
{ padding: 10 }Flips the menu to the opposite side if there is insufficient space.
offset
OffsetOptions
Default:
10Distance between the menu and its trigger.
resize
boolean
Default:
trueConstrains the menu to fit within available viewport space. When enabled, use Menu.ScrollView inside Content for scrollable overflow.
unstyled
boolean
Removes all default Tamagui styles.
Menu.Portal
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.
Menu.TriggerGroup
Wrap related menu triggers in Menu.TriggerGroup to make a web menubar. Hovering
an enabled sibling switches menus once a menu in that group is open. Hovering
an idle group does not open a menu. Each panel opens at its own trigger.
The container accepts Tamagui Props and dir="ltr" | "rtl".
It lays out triggers in a row. Left and right arrow keys move between enabled
triggers and wrap at either end. While a menu is open, they switch to the next
menu and focus its first item. Submenu opening and closing keys keep their
usual behavior. Escape closes the menu and returns focus to its active trigger.
You can also place a trigger group inside one Menu whose triggers share a
single content panel. Use trigger onMouseEnter and onFocus handlers to
prepare the corresponding contents. Groups are independent, and grouped web
menus are non-modal so sibling triggers remain reachable. Native platform
menus keep their platform interactions. Menu.Group continues to group items
inside a menu panel.
Menu.Trigger
Trigger element for the menu. Accepts Tamagui Props.
Props
action
press|longPress
Default:
pressWorks with the native prop and accepts 'press' or 'longPress'. The default is 'press' for Menu.
Menu.Content
Contains the content of the menu.
Props
children (required)
React.ReactNode
Menu items, groups, labels, separators, and submenus.
loop
boolean
Default:
falseWhether 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.
Menu.Item
A selectable menu item that triggers an action when selected.
Props
key (required)
string
Unique identifier for the item.
disabled
boolean
Default:
falsePrevents 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.
Menu.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.
Menu.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 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.ItemImage
A component to render an item image. For native menus, it only works on iOS. It
takes the same props as @tamagui/image.
Menu.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.
Menu.Group
A component that groups multiple menu items together.
Props
children (required)
React.ReactNode
Menu items to group together.
Menu.CheckboxItem
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:
falsePrevents 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.
Menu.RadioGroup
Groups a set of Menu.RadioItem and manages the selected value. Works on web
and native. On native, the group is rendered as a native menu group and each
RadioItem is mapped onto the OS checkmark state so exactly one item shows as
selected at a time.
Props
children (required)
React.ReactNode
One or more Menu.RadioItem components.
value
string
The controlled value of the currently selected item.
onValueChange
(value: string) => void
Called when the selected value changes.
Menu.RadioItem
An item that can be selected inside a Menu.RadioGroup. Render a
Menu.ItemIndicator inside to show a checkmark for the active value on web;
on native the OS draws its own checkmark and the ItemIndicator child is
dropped automatically.
Props
key (required)
string
Unique identifier for the radio item.
value (required)
string
The value of this item. When it matches the parent RadioGroup value, the item is selected.
disabled
boolean
Default:
falsePrevents interaction and dims the item.
hidden
boolean
Hides the item from the menu.
onFocus
() => void
Called when the item receives focus.
onBlur
() => void
Called when the item loses focus.
Menu.ItemIndicator
Use inside Menu.CheckboxItem or Menu.RadioItem to indicate when an item is checked.
This allows you to conditionally render a checkmark.
Props
children
React.ReactNode
Custom checkmark icon. Only works on web.
forceMount
true
Forces the indicator to stay mounted for animation control.
Menu.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.
Menu.Arrow
Renders an arrow pointing to the trigger.
Props
size
number | SizeToken
Width and height of the arrow.
unstyled
boolean
Removes default arrow styles.
Menu.Separator
Renders a visual divider between menu items. Web only.
Menu.Sub
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.
Menu.SubContent
Renders the content of a submenu. Same props as Menu.Content.
Menu.SubTrigger
A menu item that opens a submenu on hover or focus. Accepts the same props as
Menu.Item.
Menu.ScrollView
A scrollable container for menu items. Use this inside Menu.Content when you have many items that may overflow. The menu automatically constrains to available viewport space (via resize prop), and ScrollView handles the overflow. Scrollbars are hidden by default.
Styling
Item highlight behavior
Menu items use the focus condition for highlighting. Write it as a typed
object key or a focus: string clause. Focusing the highlighted item keeps
mouse and keyboard navigation in sync, with only one item highlighted at a time.
When you hover over an item, it receives focus, which activates the focus: clause. When you use arrow keys to navigate, focus moves to the new item, removing the highlight from the previous one.
String
Typed
Avoid using a hover: background clause 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.