Components

Menu

A Menu presents a list of options representing actions or navigation. Composed of MenuItems, Menu is usually combined with Popover to create a Dropdown.

Menus are great for collecting actions in one place so your users don't need to scan the entire document to find a feature.

Examples #

Import Syntax #

import Menu, { MenuDivider, MenuGroup, MenuItem } from 'mineral-ui/Menu';

Basic Usage #

Menus are composed of MenuDivider, MenuGroup, and MenuItem. Menus display a list of actions or navigation options.

Note

Menus normally occupy the full available width of their container. The Menus here are width-constrained for illustration purposes.

Menu item with onClick
Menu itemSecondary text
Icon at start
Icon at end
Disabled menu item

Group Title

Success variant
Warning variant
Danger variant
<DemoLayout>
  <Menu>
    <MenuItem onClick={event => { console.log(event) }}>
      Menu item with onClick
    </MenuItem>
    <MenuItem secondaryText="Secondary text">
      Menu item
    </MenuItem>
    <MenuItem iconStart={<IconCloud />}>Icon at start</MenuItem>
    <MenuItem iconEnd={<IconCloud />}>Icon at end</MenuItem>
    <MenuDivider />
    <MenuItem disabled onClick={event => { console.log(event) }}>Disabled menu item</MenuItem>
    <MenuGroup title="Group Title">
      <MenuItem variant="success">Success variant</MenuItem>
      <MenuItem variant="warning">Warning variant</MenuItem>
      <MenuItem variant="danger">Danger variant</MenuItem>
    </MenuGroup>
  </Menu>
</DemoLayout>

Data-Driven #

Menu content can also be defined by an array of data, with the structure shown in the code example below. Object properties will be passed on to the MenuItem.

MenuDividers are created simply by passing { divider: true } as an item.

MenuGroups are created simply by passing { group: true, title: 'Group Title' } as an item.

Menu item with onClick
Menu itemSecondary text
Icon at start
Icon at end
Disabled menu item

Group Title

Success variant
Warning variant
Danger variant
() => {
  const data = [
    {
      text: 'Menu item with onClick',
      onClick: event => { console.log(event); }
    },
    {
      text: 'Menu item',
      secondaryText: 'Secondary text'
    },
    {
      text: 'Icon at start',
      iconStart: <IconCloud />
    },
    {
      text: 'Icon at end',
      iconEnd: <IconCloud />
    },
    {
      divider: true
    },
    {
      text: 'Disabled menu item',
      disabled: true,
      onClick: () => { console.log('onClick is not triggered for disabled items'); }
    },
    {
      group: true,
      title: 'Group Title'
    },
    {
      text: 'Success variant',
      variant: 'success'
    },
    {
      text: 'Warning variant',
      variant: 'warning'
    },
    {
      text: 'Danger variant',
      variant: 'danger'
    }
  ];

  return (
    <DemoLayout>
      <Menu data={data} itemKey="text" />
    </DemoLayout>
  );
}

Custom Item #

Use the item render prop to provide custom rendering control of all MenuItems in the Menu. See our Render Props Guide for additional information, including important considerations and examples.

NewtonNewtonPrincipia Mathematica
DescartesDescartesLa Géométrie
EuclidEuclidElements
() => {
  const Div = styled('div')(
    ({ disabled, isHighlighted, theme }) => ({
      ...componentStyleReset(theme),

      backgroundColor: isHighlighted && theme.color_theme_20,
      display: 'flex',
      padding: theme.space_inset_sm + ' ' + theme.space_inset_md,
      textDecoration: 'none',

      '&:focus': {
        backgroundColor: !disabled && theme.color_theme_20,
        outline: 0
      },

      '&:hover': {
        backgroundColor: !disabled && theme.color_theme_20
      },

      '&:active': {
        backgroundColor: !disabled && theme.color_theme_40
      }
    })
  );

  const Work = styled('span')(({ theme }) => ({
    color: theme.color_mouse,
    display: 'block',
    fontSize: theme.fontSize_mouse,
    marginTop: theme.space_stack_xs
  }));

  const UserAvatar = styled(Avatar)(({ theme }) => ({
    display: 'block',
    flex: '0 0 auto',
    height: pxToEm(36),
    marginLeft: theme.direction === 'rtl' && theme.space_inset_sm,
    marginRight: theme.direction === 'ltr' && theme.space_inset_sm,
    width: pxToEm(36)
  }));

  const Content = styled('span')(({ theme }) => ({
    flex: '1 1 auto',
    fontSize: theme.fontSize_ui,
    whiteSpace: 'normal',
    wordBreak: 'break-all'
  }));

  class CustomItem extends React.PureComponent {
    render() {
      const { item } = this.props;
      return(
        <Div {...this.props}>
          {item.avatar && (
            <UserAvatar>
              <img src={item.avatar} alt={item.text} />
            </UserAvatar>
          )}
          <Content>
            {item.text}
            {item.work && <Work>{item.work}</Work>}
          </Content>
        </Div>
      );
    }
  }

  const item = ({ props }) => <CustomItem {...props} />;

  const data = [
    {
      avatar: '/images/avatar.svg',
      text: 'Newton',
      work: 'Principia Mathematica'
    },
    {
      avatar: '/images/avatar.svg',
      text: 'Descartes',
      work: 'La Géométrie'
    },
    {
      avatar: '/images/avatar.svg',
      text: 'Euclid',
      work: 'Elements'
    }
  ];

  return (
    <DemoLayout>
      <Menu data={data} item={item} itemKey="text" />
    </DemoLayout>
  );
};

API & Theme #

Menu Props #

The Menu component takes the following React props.

NameTypeDefaultDescription
childrenReact$Node
dataMenuItems

Data used to contruct Menu. See example

item

Provides custom rendering control for the items. See the custom item example and our render props guide.

itemKeystring

Specifies a key in the item data that gives an item its unique identity. See the React docs.

Undocumented properties, including as and css, will be applied to the root element.

Usage #

When/How to Use #

A Menu should be used whenever you need to display a concise list of options to your user. Think through the consequenses of the actions in your Menu. If there are potentially destructive actions exposed, be sure to use the correct variants to provide a hint to the user about what will happen after picking an option.

Labels should have clear messaging in the form of <verb> <noun>, if possible.

Best Practices #

Don't use a Menu as a general list. Items in a Menu should be actionable.

Broccoli
Cherry tomatoes
Lemon
Linguine
Garlic
Red pepper flakes
Salmon