OptionMenu
OptionMenus present a list of three or more related actions that that are displayed after a trigger button is clicked.
Button element
An OptionMenu must have a button element to trigger it. Typically, a Button component is used with ButtonDecorator.Dropdown to render the ChevronDown icon. Any element can be used here, but when using a custom element make sure it is a button html element for accessibility, otherwise the focus management handled by OptionMenu will run into problems.
Editable example<OptionMenu button={<Button decorator={ButtonDecorator.Dropdown}>Options</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
Best practices
- Avoid using an
OptionMenuif the number of options is two or less. A better component to use in that case is a . - Avoid mixing and matching selectable
OptionMenuItems with non-selectableOptionMenuItems. - Use a succinct label of 1—3 words for the trigger button and avoid long or complex words.
Sizes
The size prop determines the width of the OptionMenu menu popover element. Generally use the medium size, but small can be used for more compact layouts, while large is useful to prevent longer OptionMenuItems from spanning multiple lines.
Editable example<OptionMenu size="small" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Small</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
<OptionMenu size="medium" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Medium</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
<OptionMenu size="large" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Large</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
Separator
Use the OptionMenuSeparator to separate menu items that fall into different logical groups, or to separate destructive actions from other options. OptionMenuSeparator is a simple wrapper around the component with some default spacing applied to sit correctly within an OptionMenu.
Editable example<OptionMenu button={<Button decorator={ButtonDecorator.Dropdown}>Options</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
<OptionMenuSeparator />
<OptionMenuItem destructive>Destructive action</OptionMenuItem>
</OptionMenu>
Position
Set a preferred position and alignment for the menu relative to its trigger button. Defaults to "bottom" and "center". If there isn't enough space the menu will reposition itself.
Editable example<OptionMenu position="bottom" alignment="start" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Bottom / Start</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
<OptionMenu position="bottom" alignment="center" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Bottom / Centre</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
<OptionMenu position="right" alignment="start" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Right / Start</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuItem>Option 3</OptionMenuItem>
</OptionMenu>
You can also fine-tune the gap between the button and menu with offset (defaults to 4).
Theme
Set the visual theme for the menu. The theme prop is optional and defaults to "light".
Editable example<OptionMenu theme="light" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Light</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
</OptionMenu>
<OptionMenu theme="dark" button={<Button type={ButtonType.Secondary} decorator={ButtonDecorator.Dropdown}>Dark</Button>}>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
</OptionMenu>
Controlled
By default the menu manages its own open/closed state. Pass isOpen and onClose to take over control. You can also set closeOnOuterClick to false to keep the menu open when clicking outside it.
Editable example() => {
const [isOpen, setIsOpen] = React.useState(false);
return (
<OptionMenu
isOpen={isOpen}
onClose={() => setIsOpen(false)}
button={<Button decorator={ButtonDecorator.Dropdown} onClick={() => setIsOpen(!isOpen)}>Controlled</Button>}
>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
</OptionMenu>
);
}
Auto-stacking
The menu automatically manages its z-index using the system. Set autoStack to false if you need to handle z-index yourself.
Usage with <Popover> and other nested portal components
You can have a mix of children inside an OptionMenu, however for nested portal components you need to manually control the focus trap state for the OptionMenu component.
Use the OptionMenuNestedPortalConsumer context to update the focus trap state.
Editable example<OptionMenu
button={<Button decorator={ButtonDecorator.Dropdown}>Options</Button>}
>
<OptionMenuItem>Option 1</OptionMenuItem>
<OptionMenuItem>Option 2</OptionMenuItem>
<OptionMenuNestedPortalConsumer>
{(context) => (
<Popover
className={"nested-portal"}
position={"right"}
button={(buttonProps) => (
<OptionMenuItem {...buttonProps} closeOnClick={false}>
Nested Portal
</OptionMenuItem>
)}
onChange={(isOpen) => {
if (isOpen) {
context.deactivateFocusTrap();
} else {
context.activateFocusTrap();
}
}}
>
<Stack gap="s">
<Text>You can move focus into this nested portal</Text>
<Button>Button</Button>
</Stack>
</Popover>
)}
</OptionMenuNestedPortalConsumer>
</OptionMenu>
Accessibility
By default, OptionMenu takes care of all the accessibility for you. You only need to be careful if you take over control of its state. By default, pressing the Esc key, blurring the menu, and clicking outside closes the menu. You will need to implement this behavior yourself if you take control of its state using the isOpen prop.