NavList
NavList renders a vertical list of navigation links.
Page navigation navigation
NavLists should always be labeled for assistive technologies, even if the label is visually hidden.
NavList items are links, so they should never contain buttons or other clickable elements.
Inactive NavList items
Inactive NavList items are not rendered as <a> tags since we don't know the href value. The only focusabe part of the item is the leading visual. See the ActionList accessibility guidelines for more details.
Leading Visuals
Leading visuals are intended to be decorative only; the context of the leading visual should be provided in the text of NavList.Item. Only the text in NavList.item and any trailing visuals within NavList.Item are included in its accessible name, while anything inside NavList.LeadingVisual will be ignored.
Accessibility and usability expectations
Presentation
Cognition
- Groups should be visually related, to help make the options clearer
- Navigation items should use clear, easy to understand language
- When using nested subnav items, the structure should be clear
Vision
- When using leading and trailing visuals, or trailing actions, ensure that the icons have a color contrast ratio of at least 3:1 against the relevant item's background color
- Ensure that navigation items' text has a color contrast ratio of at least 4.5:1
- Ensure that the current navigation item communicates that it is the current item, in a way that doesn’t rely on color alone, and that the identifier has a color contrast ratio of at least 3:1 against the tree’s background color
Mobility
- Every navigation item, as well as every trailing action, must have a minimum target size of 24 by 24 CSS pixels. This is to ensure that the control is large enough to be easily activated by users with motor impairments
NavLists that have a "Show more" control, when activated, must redirect focus to the first of the newly displayed navigation items
Adaptability
- Make sure that navigation items can be increased up to 200%, and remain fully visible
- Every navigation item must remain readable and not require horizontal scrolling to read it or operate it, at a viewport size of 320 by 256 CSS pixels
- When adding additional text spacing, make sure that all navigation items can still be read in their entirety
Interaction
Keyboard
- Each navigation item must receive focus when navigating with the
Tabkey - The
Enterkey should select the navigation item - Navigation items, and any subsequently nested subnav items, or trailing actions, must receive focus in a logical order, which in the majority of cases, will be the order that they are visually displayed
Touch and mouse
- Expanding subnav items, and interacting with navigation items and trailing actions must be activated on the up event, and not the down event, or there must be a way to prevent the action from taking place on the down event
Engineering for compatibility with assistive technology
Screen reader
- The order in which the navigation items are implemented should result in a logical reading order
- The nesting of subitems in the navigation items must be communicated
- The
NavListand any subsequent nested subnavs, must have an accessible name - Navigation items must have a
roleoflink, to help convey how people can interact with these controls - Selected and currently active nodes must programmatically convey when they are selected
NavLists with subnav items must programmatically convey when they are collapsed and expanded- If using groups within the
NavListcomponent, the heading levels used must help maintain the structure and hierarchy of the page - Trailing actions must have an accessible name to describe the purpose of the control
Speech recognition
- All navigation items must include the visible label text in their accessible name
- Trailing actions should also include the visible label in their accessible names, to help people using voice control software to interact with them
Built-in accessibility features
This component is rendered as a navigation element, with an unordered list of navigation items. This helps to convey the number of items available to people using assistive technologies.
Nested subnavs follow a similar structure, and are marked up in their own unordered lists, albeit, inside the list item element of the navigation item that they relate to. Along with this, the parent item for the subnav, is automatically provided with an aria-expanded attribute, which programmatically conveys the state of the item.
An example of the rendered HTML for this pattern is as follows:
<nav>
<ul …>
<li …>
<button
type="button"
tabindex="0"
aria-labelledby="«rq3»--label «rq3»--trailing-visual "
id="«rq3»"
aria-expanded="true"
aria-controls="«rq4»"
…
>
…
<span id="«rq3»--label" …>Item 1</span>
<span … id="«rq3»--trailing-visual">
<svg aria-hidden="true" …>…</svg>
</span>
…
</button>
<ul … id="«rq4»" aria-labelledby="«rq3»">
<li …>
<a … tabindex="0" aria-labelledby="«rq6»--label " id="«rq6»" aria-current="page" href="#" …>
…
<span id="«rq6»--label" …>Sub item 1</span>
…
</a>
</li>
<li …>
<a … tabindex="0" aria-labelledby="«rq7»--label " id="«rq7»" href="#" …>
…
<span id="«rq7»--label" …>Sub item 2</span>
…
</a>
</li>
</ul>
</li>
<li …>
<a … tabindex="0" aria-labelledby="«rq8»--label " id="«rq8»" href="#" …>
…
<span id="«rq8»--label" …>Item 2</span>
…
</a>
</li>
<li …>
<a … tabindex="0" aria-labelledby="«rq9»--label " id="«rq9»" href="#" …>
…
<span id="«rq9»--label" …>Item 3</span>
…
</a>
</li>
</ul>
</nav>
Separate groups (created using multiple <NavList.Group>s) are wrapped in list item elements, in an unordered list, providing consistency across the various NavList patterns.
Implementation requirements
The NavList component must be given a group label to help convey the purpose of the component, and provide context as to what the different navigation items relate to.
This can be achieved in a few different ways:
If there’s already a visible label that relates to the <NavList> component, use the aria-labelledby prop to reference the id of the visible label. For example:
<label id="your-org-label" …>Your organization</label>
<NavList aria-labelledby="your-org-label" …>
…
This method can also be used with an sr-only heading.
Alternatively, you can use the aria-label prop to provide the component with an accessible name. For example:
<NavList aria-label="Your organization" …>
…
Setting the state of the active navigation item
When a navigation item is selected, we might change the style of the related control, to make it visually apparent that the state of this control is different. Along with the visual change, we need to make sure that we convey this information programmatically too. We can achieve this with the aria-current prop.
The prop takes a few different values, so you'll need to think about the context of use for the component and how you've used it. The following list includes the most common values for the NavList component:
page: When theNavListis displaying a set of pages, and you want to convey which of those is currently selected (useful for breadcrumb patterns)step: When theNavListis displaying a multi-step process, and you want to convey which step the user is currently ontrue: When theNavListis displaying a set of items, and you want to convey which of those is currently selectedfalse: When an item is not currently selected
For example, here's the prop used to convey that "Item 1" is currently selected and displayed:
<NavList aria-label="Test items">
<NavList.Item href="#" aria-current="page">
Item 1
</NavList.Item>
…
</NavList>
For a NavList component, only a single navigation item should have an active aria-current attribute at any given time. Multiple aria-current attributes with selected values might confuse people, and make it difficult to understand which item is active.
Naming trailing actions
When you use the <NavList.TrailingAction>, you must also provide a label prop, to provide an accessible name, which will be announced by screen readers.
For each label, describe the purpose of the control, for example, "Pin item 1". For example:
<NavList.TrailingAction>
label="Pin item 1"
icon={PinIcon}
onSelect={() => {
…
}}
/>
How to test the component
Integration tests
- If the navigation items label text is visible at wide viewports, ensure that it is not hidden or truncated at narrow viewports
- If using groups within the
NavListcomponent, the heading levels used must help maintain the structure and hierarchy of the page
Component tests
- The
NavListcomponent is exposed as a<nav>element, and an appropriate accessible name - Each navigation item is exposed as a
link, with an appropriate accessible name - Where a navigation item contains a trailing action, the control has a text alternative to provide equivalent information
- Selected navigation items convey their state using the
aria-currentattribute, and an appropriate value - Each navigation item and any trailing actions, all meet the minimum target size requirement of 24 by 24 CSS pixels
- Where a "Show more" control is included, when activated, it redirects focus to the expanded content
- Each navigation item and control in the
NavListcomponent receives focus - Each navigation item and control in the
NavListcomponent can be activated using only a keyboard