Skip to main content

Menu

Used to display a list of navigational locations.

Import

import {
  MenuProvider,
  MenuButton,
  MenuList,
  MenuItem,
  MenuDivider,
} from '@pluralsight/headless-styles'

Anatomy

  1. Trigger
  2. Container
  3. Menu
  4. Menu Item
  5. Icon (optional)
  6. Label Text
  7. Divider (optional)

Usage

The Menu events are currently being over-writen by the docs site so the interactions here won't be exactly the same as using it in your app. We are working on a fix for this and hope to have a new docs site soon.

Basic Menu

function MenuExample() {
  return (
    <MenuProvider>
      <MenuButton>Show Menu</MenuButton>
      <MenuList>
        <MenuItem href="/">Page one</MenuItem>
        <MenuItem href="/">Page two</MenuItem>
        <MenuItem href="/">Page three</MenuItem>
      </MenuList>
    </MenuProvider>
  )
}

If you need to use a custom Link component for frameworks like Next or Remix, you can pass it to the as prop on the MenuItem component.

To add an icon to the start of a MenuItem, pass the icon component to the icon prop on the MenuItem component.

function MenuItemIconExample() {
  return (
    <MenuProvider>
      <MenuButton>Show Menu</MenuButton>
      <MenuList>
        <MenuItem href="/" icon={PlaceholderIcon}>
          Page one
        </MenuItem>
        <MenuItem href="/" icon={PlaceholderIcon}>
          Page two
        </MenuItem>
        <MenuItem href="/" icon={PlaceholderIcon}>
          Page three
        </MenuItem>
      </MenuList>
    </MenuProvider>
  )
}

To add a divider between MenuItems, use the MenuDivider component.

function MenuItemDividerExample() {
  return (
    <MenuProvider>
      <MenuButton>Show Menu</MenuButton>
      <MenuList>
        <MenuItem href="/">Page one</MenuItem>
        <MenuDivider />
        <MenuItem href="/">Page two</MenuItem>
        <MenuDivider />
        <MenuItem href="/">Page three</MenuItem>
      </MenuList>
    </MenuProvider>
  )
}

Customizing

There are 3 ways to customize the Menu components.

1. Unused Classes

Each component layer of the Menu has a unused class name that can be utilized in your local CSS to customize the Menu at any level.

  1. pando-menu-list-container: The container of the Menu.
  2. pando-menu-list: The list elmenet of the Menu.
  3. pando-menu-list-item: The list item element of the Menu.
  4. pando-menu-list-item-content: The content of the Menu.
  5. pando-menu-list-item-divider: The divider element of the Menu.
  6. pando-icon: The icon element of the Menu.
  7. pando-btn: The button element of the Menu.

2. Passing a className prop

You can pass a className prop to the Menu components to customize the Menu at the container, heading, or text level. This is useful if your project uses CSS Modules or a CSS-in-JS library like Emotion.

import customStyles from './customStyles.module.css'

function CustomMenu(props) {
  return (
    <MenuProvider>
      <MenuButton className={customStyles.btn}>Settings</MenuButton>
      <MenuList className={customStyles.list}>
        <MenuItem href="/" className={customStyles.item}>
          Page one
        </MenuItem>
        <MenuItem href="/" className={customStyles.item}>
          Page two
        </MenuItem>
        <MenuItem href="/" className={customStyles.item}>
          Page three
        </MenuItem>
      </MenuList>
    </MenuProvider>
  )
}

3. Ejected Menu

For a low-level "ejected" approach, you can use the Headless-styles API to customize the Menu however you prefer while keeping the accessibility behavior.

import {
  getMenuListContainer,
  getMenuButtonProps,
  getMenuListProps,
  getMenuListItemProps,
} from '@pluralsight/headless-styles'

To learn more about the Headless-styles API, check out the Headless-styles documentation.

Behavior

Do: use the Menu component to display a list of navigational locations.

Don't: use the Menu component to display a list of actions. Instead use the ActionMenu component.

API

Parameters

The MenuProvider component does not accept any parameters.

Parameters

type MenuButtonProps = HTMLAttributes<HTMLButtonElement>

The MenuButton component accepts all props that a standard HTML button element accepts and returns a text usage of the Button component.

Parameters

type MenuListProps = HTMLAttributes<HTMLUListElement>

The MenuList component accepts all props that a standard HTML ul element accepts.

Parameters

interface MenuItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
  as?: AnchorHTMLAttributes<HTMLAnchorElement> | ElementType
  icon?: ElementType
}
  • any props that a standard HTML a element accepts
  • as: The as prop allows you to render the MenuItem as a different HTML element or React component. This is useful if you want to render the MenuItem as a Link component from a routing library like React Router.
  • icon: The icon prop allows you to render an icon component to the start of the MenuItem.

Parameters

The MenuDivider component does not accept any parameters.

Accessibility

The Pando Menu and Icon APIs combined with semantic HTML allow the Menu to be fully accessible and screen-readable.

Keyboard Navigation

The Menu component supports keyboard navigation. When the Menu is open, the user can use the Home/End key to navigate to the start or end the MenuItems. The user can also use the ArrowUp and ArrowDown keys to navigate through the MenuItems.

Screen Readers

The Menu component is screen-reader accessible. When the Menu is open, the screen reader will read the MenuItems in the order they appear in the DOM.

Color Contrast

The Menu component meets the WCAG AA contrast ratio requirements for text and icons.

Focus Management

The Menu component manages focus. When the Menu is open, the MenuItems are focusable and the MenuButton is not focusable. When the Menu is closed, the MenuButton is focusable and the MenuItems are not focusable.