RowMenu

Organism
Vertical action menu items and navigation links.

Playground

Every control sets a real prop of RowMenuProps. The JSX below updates as you go.
Props
open
boolean
triggerLabel
string
sectionLabel
string
JSX · RowMenuProps
<RowMenu open triggerLabel="Row actions" />

Variants

4 examples from src/organisms/row-menu/row-menu.md, each rendered live from its own JSX.
Links
<RowMenu links items={[{ label: "Profile" }, { label: "Billing" }, { label: "Members" }]} />
Section label
<RowMenu sectionLabel="Actions" items={[{ label: "Edit" }, { label: "Duplicate" }, { label: "Rename" }]} />
Leading icons
<RowMenu
items={[
{ label: "Edit", icon: "pencil" },
{ label: "Duplicate", icon: "copy" },
{ label: "Settings", icon: "settings" }
]}
/>
Disabled item
Mark an item disabled when its action is unavailable in the current context; the row dims, does not fire onSelect, keeps the menu open, and is announced as disabled.
<RowMenu items={[{ label: "Edit" }, { label: "Duplicate" }, { label: "Clear column", disabled: true }]} />

Anatomy

1
Trigger
2
Menu
3
Item
4
Destructive item
Dimmed parts appear only in some states or variants.

Props

10 props on RowMenuProps, grouped as they are declared in source. Required props are marked *.
Prop
Type
Default
Description
Props
10 props
items *
RowMenuItem[]
–
The menu rows, top to bottom.
open
boolean
false
Controlled open state. Omit for uncontrolled (the trigger toggles it).
onOpenChange
(open: boolean) => void
–
Fired when the open state changes.
links
boolean
false
Render rows as navigation links rather than action buttons.
inline
boolean
false
The menu drawn in place, with no ⋯ trigger and no overlay: the action rows in the menu's own panel, filling the width the parent gives it. With links it is a grouped link list instead: hairline-split rows, each ending in its badge or meta and a chevron. open, onOpenChange and triggerLabel do nothing here.
sectionLabel
string
–
Show a muted section label heading the menu.
onSelect
(item: RowMenuItem, index: number) => void
–
Fired with the selected item and its index when a row is pressed.
triggerLabel
string
"More options"
Accessible name for the icon-only ⋯ trigger. Defaults to "More options".
testID
string
–
E2E hook forwarded to the root element.
style
LayoutStyle
–
Composition within a parent only, never a restyle hook and never a width: the parent layout container provides the bounds.

Accessibility and keyboard

Keyboard
Enter
Space
ArrowDown
Opens the menu
ArrowUp
ArrowDown
Moves between items
Home
End
First · last item
Enter
Chooses the item
Escape
Closes, focus returns to the trigger
Semantics
Roles
button
link
menu
menuitem
States
expanded
ARIA on web
aria-disabled
aria-expanded
aria-haspopup
aria-label
Below the platform minimum, the touch area grows to 44 pt on iOS and 48 dp on Android without moving the layout.

Platform skins

The playground's props on each platform: same tree, native shapes, type and touch sizes.
Profile
Notifications
3 new
Integrations
3
Web
control 10 · field 10 · card 16 · Instrument Sans
Profile
Notifications
3 new
Integrations
3
iOS
capsule controls · field 8 · card 12 · SF Pro · 44 pt
Profile
Notifications
3 new
Integrations
3
Android
Material 3 stadium · field 4 · card 12 · Roboto · 48 dp

Usage

<RowMenu
items={[
{ label: "Edit" },
{ label: "Duplicate" },
{ label: "Delete", destructive: true, separatorBefore: true }
]}
/>
On the web the ··· trigger is a 32px square on the field hairline, washed while its menu is open or under the pointer, and it opens a card menu 220 wide: rows 34 tall with a muted leading glyph beside the label, and a destructive row in red. iOS and Android keep their platform context menus in the theme's colours.
In glass mode the menu is a dense-layer glass card beside its glyph; a row's callback fires the moment it is pressed. Solid mode paints the skin's own menu. Board's card menus are RowMenus and behave the same.

Tokens

Read from the playground render. Values follow the scheme and the ion hue.
--bad
--fd
--ft
--ln
--ln2
--sf
--sf3
--sh-md
--tx3

Related components