A list of actions in a dropdown, enhanced with keyboard navigation.
import { MenuTrigger, Menu, MenuItem } from '@backstage/ui';
<MenuTrigger>
<Button>Menu</Button>
<Menu>
<MenuItem id="apple">Apple</MenuItem>
<MenuItem id="banana">Banana</MenuItem>
<MenuItem id="blueberry">Blueberry</MenuItem>
<MenuSeparator />
<SubmenuTrigger>
<MenuItem>Vegetables</MenuItem>
<Menu>
<MenuItem id="carrot">Carrot</MenuItem>
<MenuItem id="tomato">Tomato</MenuItem>
<MenuItem id="potato">Potato</MenuItem>
</Menu>
</SubmenuTrigger>
</Menu>
</MenuTrigger>MenuTrigger is a wrapper component that combines a button or other trigger element with a menu displayed in a popover.SubmenuTrigger is a wrapper component that combines a MenuItem with a menu displayed in a popover.Menu is a container component that contains a list of menu items or sections.MenuListBox is a container component that contains a list of menu items or sections.MenuAutocomplete is a container component that contains a list of menu items or sections.MenuAutocompleteListbox is a container component that contains a list of menu items or sections.MenuItem is an individual interactive item in the menu.MenuListBoxItem is an individual interactive item in the menu list box.MenuSeparator is a component that renders a horizontal line to separate menu items.MenuSection is a component that renders a section in the menu.MenuTrigger accepts exactly two children: the first child should be the trigger element, and second child should be
one of the menu containers containing the menu.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| isOpen | boolean | - | No |
| defaultOpen | boolean | - | No |
| onOpenChange | (isOpen: boolean) => void | - | No |
The SubmenuTrigger accepts exactly two children: the first child should be the MenuItem which triggers opening
of the submenu, and second child should be one of the menu containers containing the submenu.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| delay | number | 200 | No |
Menu is a container component that contains a list of menu items or sections.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| disabledKeys | Iterable<Key> | - | No |
| selectionMode | nonesinglemultiple | - | No |
| selectedKeys | allIterable<Key> | - | No |
| defaultSelectedKeys | allIterable<Key> | - | No |
| placement | bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom | - | No |
| virtualized | boolean | false | No |
| maxWidth | number | - | No |
| maxHeight | number | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuListBox is a container component that contains a list of menu items or sections.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| disabledKeys | Iterable<Key> | - | No |
| selectionMode | nonesinglemultiple | - | No |
| selectedKeys | allIterable<Key> | - | No |
| defaultSelectedKeys | allIterable<Key> | - | No |
| placement | bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom | - | No |
| virtualized | boolean | false | No |
| maxWidth | number | - | No |
| maxHeight | number | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuAutocomplete is a container component that contains a list of menu items or sections.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| placement | bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom | - | No |
| virtualized | boolean | false | No |
| maxWidth | number | - | No |
| maxHeight | number | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuAutocompleteListbox is a container component that contains a list of menu items or sections.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| placement | bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom | - | No |
| virtualized | boolean | false | No |
| maxWidth | number | - | No |
| maxHeight | number | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuItem is an individual interactive item in the menu.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| id | Key | - | No |
| value | string | - | No |
| textValue | string | - | No |
| isDisabled | boolean | - | No |
| href | string | - | No |
| onAction | (event) => void | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuListBoxItem is an individual interactive item in the menu list box.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| id | Key | - | No |
| value | string | - | No |
| textValue | string | - | No |
| isDisabled | boolean | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuSection is a component that renders a section in the menu.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| title | string | - | No |
| className | string | - | No |
| style | CSSProperties | - | No |
MenuSeparator is a component that renders a horizontal line to separate menu items.
| Prop | Type | Default | Responsive |
|---|---|---|---|
| className | string | - | No |
| style | CSSProperties | - | No |
You can nest menus to create a more complex navigation structure. It is important to use the placement prop to ensure
the submenu is displayed in the correct position. The best practice is to use the right top placement for the submenu.
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<Menu>
<MenuItem>Edit</MenuItem>
<MenuItem>Duplicate</MenuItem>
<SubmenuTrigger>
<MenuItem>Submenu</MenuItem>
<Menu placement="right top">
<MenuItem>Edit</MenuItem>
<MenuItem>Duplicate</MenuItem>
<MenuItem>Rename</MenuItem>
<MenuSeparator />
<MenuItem>Share</MenuItem>
<MenuItem>Move</MenuItem>
<MenuSeparator />
<MenuItem iconStart={<RiChat1Line />}>Feedback</MenuItem>
</Menu>
</SubmenuTrigger>
</Menu>
</MenuTrigger>You can use the iconStart prop to add an icon to the menu item.
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<Menu>
<MenuItem iconStart={<RiFileCopyLine />}>Copy</MenuItem>
<MenuItem iconStart={<RiEdit2Line />}>Rename</MenuItem>
<MenuItem iconStart={<RiChat1Line />}>Send feedback</MenuItem>
</Menu>
</MenuTrigger>You can use the href prop to add a link to the menu item. This is using our router provider under the hood
to work for both internal and external links.
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<Menu>
<MenuItem href="/home">Internal link</MenuItem>
<MenuItem href="https://www.google.com" target="_blank">
External link
</MenuItem>
<MenuItem href="mailto:test@test.com">Email link</MenuItem>
</Menu>
</MenuTrigger>You can use the MenuSection component to add a section to the menu.
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<Menu>
<MenuSection title="My Account">
<MenuItem iconStart={<RiUserLine />}>Profile</MenuItem>
<MenuItem iconStart={<RiSettingsLine />}>Settings</MenuItem>
</MenuSection>
<MenuSection title="Support">
<MenuItem iconStart={<RiQuestionLine />}>Help Center</MenuItem>
<MenuItem iconStart={<RiCustomerService2Line />}>
Contact Support
</MenuItem>
<MenuItem iconStart={<RiChat1Line />}>Feedback</MenuItem>
</MenuSection>
</Menu>
</MenuTrigger>You can use the MenuSeparator component to add a separator to the menu.
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<Menu>
<MenuItem>Edit</MenuItem>
<MenuItem>Duplicate</MenuItem>
<MenuItem>Rename</MenuItem>
<MenuSeparator />
<MenuItem>Share</MenuItem>
<MenuItem>Move</MenuItem>
<MenuSeparator />
<MenuItem iconStart={<RiChat1Line />}>Feedback</MenuItem>
</Menu>
</MenuTrigger>You can use the MenuAutocomplete component to add a autocomplete to the menu.
<MenuTrigger isOpen>
<Button aria-label="Menu">Menu</Button>
<MenuAutocomplete placeholder="Filter">
<MenuItem>Create new file...</MenuItem>
<MenuItem>Create new folder...</MenuItem>
<MenuItem>Assign to...</MenuItem>
<MenuItem>Assign to me</MenuItem>
<MenuItem>Change status...</MenuItem>
<MenuItem>Change priority...</MenuItem>
<MenuItem>Add label...</MenuItem>
<MenuItem>Remove label...</MenuItem>
</MenuAutocomplete>
</MenuTrigger>You can use the MenuListBox component to add a list box to the menu.
const [selected, setSelected] = useState<Selection>(
new Set(['blueberry']),
);
<Flex direction="column" gap="2" align="start">
<Text>Selected: {Array.from(selected).join(', ')}</Text>
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<MenuAutocompleteListbox
selectedKeys={selected}
onSelectionChange={setSelected}
>
{options.map(option => (
<MenuListBoxItem key={option.value} id={option.value}>
{option.label}
</MenuListBoxItem>
))}
</MenuAutocompleteListbox>
</MenuTrigger>
</Flex>You can use the MenuListBox component to add a list box to the menu. You can also use the selectionMode prop to
allow multiple selection.
const [selected, setSelected] = useState<Selection>(
new Set(['blueberry', 'cherry']),
);
<Flex direction="column" gap="2" align="start">
<Text>Selected: {Array.from(selected).join(', ')}</Text>
<MenuTrigger>
<Button aria-label="Menu">Menu</Button>
<MenuAutocompleteListbox
selectionMode="multiple"
selectedKeys={selected}
onSelectionChange={setSelected}
>
{options.map(option => (
<MenuListBoxItem key={option.value} id={option.value}>
{option.label}
</MenuListBoxItem>
))}
</MenuAutocompleteListbox>
</MenuTrigger>
</Flex>Our theming system is based on a mix between CSS classes, CSS variables and data attributes. If you want to customise this component, you can use one of these class names below.
bui-Menubui-MenuPopoverbui-MenuContentbui-MenuSectionbui-MenuSectionHeaderbui-MenuItembui-MenuItemListBoxbui-MenuItemListBoxCheckbui-MenuItemWrapperbui-MenuItemContentbui-MenuItemArrowbui-MenuSeparatorbui-MenuSearchFieldbui-MenuSearchFieldInputbui-MenuSearchFieldClearbui-MenuEmptyState