Version 0.7.0 - Alpha
Menu
component

Menu

A list of actions in a dropdown, enhanced with keyboard navigation.

Usage

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>

Triggers

Containers

Items

Separators

API reference

MenuTrigger

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.

PropTypeDefaultResponsive
isOpen
boolean
-No
defaultOpen
boolean
-No
onOpenChange
(isOpen: boolean) => void
-No

SubmenuTrigger

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.

PropTypeDefaultResponsive
delay
number
200No

Menu

Menu is a container component that contains a list of menu items or sections.

PropTypeDefaultResponsive
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
className
string
-No
style
CSSProperties
-No

MenuListBox

MenuListBox is a container component that contains a list of menu items or sections.

PropTypeDefaultResponsive
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
className
string
-No
style
CSSProperties
-No

MenuAutocomplete

MenuAutocomplete is a container component that contains a list of menu items or sections.

PropTypeDefaultResponsive
placement
bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom
-No
className
string
-No
style
CSSProperties
-No

MenuAutocompleteListbox

MenuAutocompleteListbox is a container component that contains a list of menu items or sections.

PropTypeDefaultResponsive
placement
bottombottom leftbottom rightbottom startbottom endtoptop lefttop righttop starttop endleftleft topleft bottomstartstart topstart bottomrightright topright bottomendend topend bottom
-No
className
string
-No
style
CSSProperties
-No

MenuItem

MenuItem is an individual interactive item in the menu.

PropTypeDefaultResponsive
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

MenuListBoxItem is an individual interactive item in the menu list box.

PropTypeDefaultResponsive
id
Key
-No
value
string
-No
textValue
string
-No
isDisabled
boolean
-No
className
string
-No
style
CSSProperties
-No

MenuSection

MenuSection is a component that renders a section in the menu.

PropTypeDefaultResponsive
title
string
-No
className
string
-No
style
CSSProperties
-No

MenuSeparator

MenuSeparator is a component that renders a horizontal line to separate menu items.

PropTypeDefaultResponsive
className
string
-No
style
CSSProperties
-No

Examples

Nested navigation

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>

With icons

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>

With links

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>

With sections

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>

With separators

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>

With autocomplete

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>

With list box

You can use the MenuListBox component to add a list box to the menu.

Selected: blueberry
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>

With list box with multiple selection

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.

Selected: blueberry, cherry
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>

Theming

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.

Changelog