Menu
Menu is the list of actions behind a button, such as the “…” on a pipeline stage or a table
row. You describe the items as data and get the chosen value in onSelect.
import { Menu } from '@beyul/sulmu-ui'Examples
Section titled “Examples”Actions
Section titled “Actions”Last chosen: nothing yet
import { Edit2Icon, IconButton, Menu, MoreIcon, Setting2Icon, Text, TrashIcon,} from '@beyul/sulmu-ui'import { useState } from 'react'
const items = [ { value: 'automation', label: 'Stage Automation', icon: <Setting2Icon /> }, { value: 'edit', label: 'Edit Stage', icon: <Edit2Icon /> }, { value: 'delete', label: 'Delete Stage', icon: <TrashIcon />, danger: true, separatorBefore: true, },]
export default function Example() { const [last, setLast] = useState('nothing yet') return ( <> <Menu trigger={<IconButton aria-label="Stage actions" variant="secondary" icon={<MoreIcon />} />} items={items} onSelect={setLast} /> <Text textStyle="caption" tone="subtle" style={{ marginTop: 12 }}> Last chosen: {last} </Text> </> )}Inverse, with a header and a toggle
Section titled “Inverse, with a header and a toggle”variant="inverse" is the dark glass panel used for the profile menu. header places content
above the items, and keepOpen keeps the menu open after choosing an item.
import { Avatar, Button, MagicStarIcon, Menu, MessageQuestionIcon, Setting2Icon, Switch,} from '@beyul/sulmu-ui'
export default function Example() { return ( <Menu variant="inverse" trigger={<Button variant="inverse">Account</Button>} header={ <div style={{ display: 'flex', gap: 12, alignItems: 'center', minWidth: 220 }}> <Avatar size="lg" name="Howard Sheldon" /> <div> <div style={{ color: 'var(--su-colors-fg-inverse)', fontSize: 14 }}>Howard Sheldon</div> <div style={{ fontSize: 12 }}>@Thenter888</div> </div> </div> } items={[ { value: 'profile', label: 'Profile', icon: <Setting2Icon />, separatorBefore: true }, { value: 'help', label: 'Help Center', icon: <MessageQuestionIcon /> }, { value: 'dark', label: 'Dark Mode', icon: <MagicStarIcon />, trailing: <Switch aria-label="Dark mode" />, keepOpen: true, }, { value: 'logout', label: 'Log Out', separatorBefore: true }, ]} /> )}| Prop | Type | Default | Description |
|---|---|---|---|
trigger* | ReactElement<unknown, string | JSXElementConstructor<any>> | - | The element that opens the menu: a Button or IconButton. |
items* | MenuItem[] | - | |
header | ReactNode | - | Content above the items, e.g. the user's avatar and name. |
variant | "inverse" | "surface" | surface | surface (default) or inverse, the dark glass panel used for the profile menu. |
onSelect | ((value: string) => void) | - | Called with the chosen item's value. |
open | boolean | - | The controlled open state of the menu |
defaultOpen | boolean | - | The initial open state of the menu when rendered. Use when you don't need to control the open state of the menu. |
onOpenChange | ((details: OpenChangeDetails) => void) | - | Function called when the menu opens or closes |
The remaining props of Ark UI’s Menu.Root are accepted too.
| Field | Type | Description |
|---|---|---|
value |
string |
Passed to onSelect when the item is chosen. Must be unique. |
label |
ReactNode |
The item text. |
icon |
ReactNode |
Shown before the label. |
disabled |
boolean |
The item cannot be chosen. |
danger |
boolean |
Destructive action, shown in the danger colour. |
trailing |
ReactNode |
Shown at the right edge: a tick, a Switch, a count. |
keepOpen |
boolean |
Keep the menu open after choosing this item (for toggles). |
separatorBefore |
boolean |
Draw a separator line above this item. |
Accessibility and usage
Section titled “Accessibility and usage”triggermust be a single element that can take a ref and props: aButtonorIconButton.- Arrow keys move through the items, Enter chooses, Escape closes and returns focus to the trigger.
- A menu is for actions. To pick a value, use Select.