All components
Navigation

Menu

stable
Since 1.2
Action menu owning its trigger and overlay, with sections, icons, shortcuts, destructive items, and a Popover for interactive content.
Navigation
primitive
Interactive
Needs State Matrix
import { Menu } from '@ivim/native/components';

When to use

Use when
A surface has secondary actions that would crowd it if always visible.
A row or card needs an overflow menu.
You need a floating surface holding interactive content — use Popover.
Don't use when
The value being chosen is a form field — use Select, which announces as a choice rather than a set of actions.
There are one or two actions with room to show them — a Button says what it does without a press to reveal it.
The content is purely descriptive — use Tooltip.

Playground

Adjust the controls to preview live prop combinations. The code snippet updates to match the current selection.
placement
placement
Inline
isInline
Trigger
triggerLabel
selectionIndicator
selectionIndicator
<Menu triggerLabel="Row actions" />

Example

Menu
Trigger and overlay
Sections and a destructive item
Descriptions, selection, and shortcuts
selectionIndicator: 'checkmark' (trailing, selected item only)
selectionIndicator: 'checkbox' (leading, every item)
selectionIndicator: 'radio' (leading, every item)
Disabled item
Inline (embedded, no trigger)
Popover
Interactive content on press

Anatomy

The parts that compose this component.
1
Trigger
Owns the open state and reports expanded.
2
Overlay
Anchored popover on web, bottom sheet on native.
3
Section
Optional heading with a separator between groups.
4
Item
Icon, label, description, and a decorative trailing addon.

Guidelines

Do
Give every item a stable key; the previous implementation keyed by array index, so reordering broke selection.
Do
Group related actions with section, and put destructive actions last with isDestructive.
Do
Set an explicit placement near a screen edge — placement is resolved against the trigger, not measured against the viewport.
Don't
Put form controls in a Menu; its items announce as menu items, not as fields. Use Popover.
Don't
Rely on a shortcut addon to convey what an item does — it is decorative and hidden from assistive tech.

Props

Public props for this component. Required props are marked; defaults reflect the component implementation.
items
required
MenuItem[]
{ key, label, description?, icon?, addon?, section?, isSelected?, isDisabled?, isDestructive?, onPress? }.
selectionIndicator
'checkmark' | 'checkbox' | 'radio' | 'none'
default: 'none'
How MenuItem.isSelected renders. 'none' keeps the highlighted-row treatment with no extra glyph; 'checkmark' adds a trailing check on the selected item; 'checkbox' / 'radio' add a leading control-shaped indicator on every item. Mirrors Untitled UI's Dropdown selectionIndicator, minus its 'toggle' value — no RN precedent for a toggle glyph in a menu row.
trigger / triggerLabel
ReactNode / string
Presentational trigger content, and its accessible name.
isOpen / defaultOpen / onOpenChange
boolean / boolean / (isOpen) => void
Controlled and uncontrolled open state.
onAction
(key: string) => void
Fires with the activated item’s key.
placement
'bottom-start' | 'bottom-end' | 'top-start' | 'top-end'
default: 'bottom-start'
Overlay position relative to the trigger, on web.
isInline
boolean
default: false
Renders the list without a trigger, for embedding.
Popover: trigger / triggerLabel / placement
ReactNode / string / PopoverPlacement
Popover holds interactive content and opens on press, unlike Tooltip.

Deviations from Untitled UI

Where this component deliberately differs from Untitled UI's API, and why. These are kept choices, not gaps to close.
Untitled UI
Compound children (`Select.Item`, `Dropdown.Root/Popover/Menu`, `Tabs.List/Panel`)
Ours
data-driven `items` / `options` / `columns` arrays
RN has no DOM portals and compound context patterns complicate static typing and testing. Typed arrays are serializable, exhaustively checkable, and match RN list idioms. See grammar rule G8.
Untitled UI
`selectionIndicator` includes `"toggle"`; default `"checkmark"`
Ours
`selectionIndicator: "checkmark" | "checkbox" | "radio" | "none"`; default `"none"`
The `"toggle"` indicator has no RN precedent in this library, so it is omitted. The default is `"none"` rather than UUI's `"checkmark"` because selection previously rendered only as a row highlight — defaulting to a glyph would silently add a checkmark to every selected item across existing menus.

Accessibility

Roles and screen-reader behavior this component provides, plus keyboard interactions.
The trigger announces its name and expanded state; items announce as menu items with selected and disabled state.
Arrow keys move the active item on web, Enter activates, and Escape dismisses.
Shortcut addons are hidden from assistive tech — the platform already exposes shortcuts, so repeating them is noise.
The overlay list is not itself an accessibility element, so items stay individually reachable on iOS.
Activating an item closes the menu, so the surface is never left in a stale open state.
Tab
Moves focus to the trigger.
Space / Enter
Opens the menu, or activates the active item.
Arrow Up / Down
Moves the active item, skipping disabled ones.
Home / End
First or last enabled item.
Escape
Dismisses the menu.

Platform & RTL

Behavior that differs across the platforms this component runs on.
Web
An anchored popover with arrow-key navigation and Escape to dismiss.
iOS
A bottom sheet — deliberate to dismiss, and comfortable to reach one-handed.
Android
A bottom sheet; the hardware back button dismisses it.
RTL
Item content and placement mirror with the writing direction.

State coverage

Interaction and visual states this component supports.
default
pressed
disabled
active

Token references

Semantic design tokens this component page exercises. Tap one to edit it live.