Expandable navigationStatusrelease
Show and hide navigation with a button.
Guidance
Use this pattern for hamburger-type navigation that expands and collapses in the document flow. The expandable navigation pattern remains open when the focus moves out of the navigation and allows interaction with the rest of the page while it is open.
Example
Dependencies and installation
Package | Installation |
---|---|
@stormid/toggle |
|
Code
<nav class="expandable-nav__nav" aria-label="Primary navigation"><button type="button" class="expandable-nav__btn js-expandable-nav__toggle" aria-label="Show navigation menu" aria-controls="expandable-nav" aria-expanded="false" data-show-label="Show navigation menu" data-hide-label="Hide navigation menu"><svg focusable="false" class="expandable-nav__btn-icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0z" fill="none"></path><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg>menu</button><div id="expandable-nav" class="expandable-nav__display-wrap js-expandable-nav" data-toggle="js-expandable-nav__toggle"><ul class="expandable-nav__list"><li class="expandable-nav__item"><a class="expandable-nav__link" href="#">Item 1</a></li><li class="expandable-nav__item"><a class="expandable-nav__link is--active" href="#" aria-current="page">Item 2</a></li><li class="expandable-nav__item"><a class="expandable-nav__link" href="#">Item 3</a></li><li class="expandable-nav__item"><a class="expandable-nav__link" href="#">Item 4</a></li><li class="expandable-nav__item"><a class="expandable-nav__link" href="#">Item 5</a></li></ul></div></nav>
import toggle from '@stormid/toggle';
const toggleInstances = toggle('.js-expandable-nav', { focus: false });
//to change the aria-label when navigation is toggled
const SHOW_LABEL_ATTRIBUTE = 'data-show-label';
const HIDE_LABEL_ATTRIBUTE = 'data-hide-label';
const toggleAriaLabel = e => {
const { toggles } = e.detail.getState();
toggles.forEach(btn => {
if (!btn.hasAttribute(SHOW_LABEL_ATTRIBUTE) && !!btn.hasAttribute(SHOW_LABEL_ATTRIBUTE)) return;
btn.setAttribute('aria-label', (btn.getAttribute('aria-expanded') === 'true') ? btn.getAttribute(HIDE_LABEL_ATTRIBUTE) : btn.getAttribute(SHOW_LABEL_ATTRIBUTE));
});
};
toggleInstances.forEach(instance => {
instance.getState().node.addEventListener('toggle.open', toggleAriaLabel);
instance.getState().node.addEventListener('toggle.close', toggleAriaLabel);
});
Acceptance criteria
The following is a list of example acceptance criteria to test against when using this pattern. These critera should test that the specific markup requirements are met, and that the navigation behaves visually and functionally as expected.
For validation in developer tools / web inspector
- An HTML
<button>
element is used to open/close the navigation - The navigation should be contained within an HTML
<nav>
element - The navigation should be labelled appropriately to describe its function (e.g. 'Primary Navigation'). This can be done by an HTML heading element being the first item in the navigation, or an
aria-label
on the<nav>
element itself - Buttons should be contained within the
<nav>
element - An
aria-expanded
attribute should be present on the toggle<button>
. The value of this should be 'true' when the navigation is visible, and 'false' when the navigation is hidden. - The toggle
<button>
element should have anaria-controls
attribute. The value of this should match the ID of the element being shown/hidden. - The currently active navigation link should have
aria-current
attribute with its value set to 'page' - Navigation toggle button labels that describe the state of the navigationshould update when toggled, e.g. 'Open' should change to 'Close'.
For visual validation
- Navigation toggle buttons should have a clearly visible focus style which meets accessibility contrast requirements
- Navigation toggle buttons should be appropriately labelled to describe their functionality. If the design requires no visible text, a label should be added as an
aria-label
attribute on the<button>
element - Navigation toggle buttons should be no less than 44px x 44px in size (unless any of the allowed WCAG exceptions apply)
- Navigation links should be hidden visually, hidden from keyboard access, and not read by screenreaders when the menu is closed
- Navigation links should be visible, available for keyboard access, and read by screenreaders when the menu is opened
- Navigation links should push down - not overlay - any page content when opened
- Moving page focus to outside of the navigation via mouse, keyboard or any other means should leave the navigation open
- Navigation link text should accurately describe the link destination
For functional validation
- Navigation toggle buttons should be available to be tabbed to and activated via keyboard
- Navigation links should be available to be tabbed to and activated via keyboard
- The close button should receive visible focus when navigation is opened
- When open, the navigation should not trap tab - a user should be able to tab out of the menu to page content below