Menu
Used to display a list of navigational locations.
Import
import {
MenuProvider,
MenuButton,
MenuList,
MenuItem,
MenuDivider,
} from '@pluralsight/headless-styles'
Anatomy
- Trigger
- Container
- Menu
- Menu Item
- Icon (optional)
- Label Text
- 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.
Menu Items with Icons
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>
)
}
Menu Items with Dividers
To add a divider between MenuItem
s, 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.
pando-menu-list-container
: The container of the Menu.pando-menu-list
: The list elmenet of the Menu.pando-menu-list-item
: The list item element of the Menu.pando-menu-list-item-content
: The content of the Menu.pando-menu-list-item-divider
: The divider element of the Menu.pando-icon
: The icon element of the Menu.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
MenuProvider
Parameters
The MenuProvider
component does not accept any parameters.
MenuButton
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.
MenuList
Parameters
type MenuListProps = HTMLAttributes<HTMLUListElement>
The MenuList
component accepts all props that a standard HTML ul
element accepts.
MenuItem
Parameters
interface MenuItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
as?: AnchorHTMLAttributes<HTMLAnchorElement> | ElementType
icon?: ElementType
}
- any props that a standard HTML
a
element accepts as
: Theas
prop allows you to render theMenuItem
as a different HTML element or React component. This is useful if you want to render theMenuItem
as aLink
component from a routing library like React Router.icon
: Theicon
prop allows you to render an icon component to the start of theMenuItem
.
MenuDivider
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.