
Security News
How Enterprise Security Is Adapting to AI-Accelerated Threats
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.
@nycopportunity/pattern-menu
Advanced tools
The Menu Pattern is an accessible sliding menu that contains the navigation items that do not fit within the Navigation Pattern in mobile viewports.
The Menu Pattern is a sliding menu that contains the navigation items that do not fit within the Navigation Pattern in mobile viewports. It uses the Patterns Scripts toggle utility to achieve the showing and hiding effects. The animation for the sliding uses CSS and will be disabled by devices using the prefers-reduced-motion @media query.
The menu element will be hidden from screen readers using the aria-hidden attribute and potentially focusable children will have their tabindex set to -1 when the modal is hidden. When the menu is opened, focus will shift from the data-js-menu="open" trigger to the data-js-menu="close" trigger inside the menu. The focus will be trapped, meaning tabbing focus will cycle through elements within the menu.
$ npm install @nycopportunity/pattern-menu
The pattern uses JavaScript to show and hide the menu. This method is a wrapper around the Patterns Scripts toggle utility which is included as a dependency of this project. The utility can be imported as an ES module and instantiated.
import Menu from '@nycopportunity/pattern-menu/src/menu';
new Menu();
The Menu Pattern includes two stylesheets. One that sets default design tokens and display properties using CSS Custom Properties and one that applies the tokens to the menu CSS selectors. The tokens can be used as is or overridden.
@import '@nycopportunity/pattern-menu/src/tokens';
@import '@nycopportunity/pattern-menu/src/menu';
The following markup is the minimum required for an opening trigger of the Menu.
<button data-js="menu" data-js-menu="open" aria-controls="aria-c-menu" aria-expanded="false">
Open Menu
</button>
| Attribute | Description |
|---|---|
data-js="menu" | Adds the toggling utility to open the menu. |
data-js-menu="open" | Indicates that this is the primary opening button for the menu. Focus will shift from the close button to the open button when the menu is closed. |
aria-controls | Targets the Menu ID for toggling. |
aria-expanded="true/false" | Indicates to screen readers that the button is active or not. This attribute will be toggled when the trigger is clicked. |
The menu ID should be same as the aria-controls attribute for the opening and closing trigger.
The script uses the toggling utility from the Patterns Scripts library. Potentially focusable elements inside the menu will need to have their tabindex set to -1 before the menu is toggled open. A full list of elements can be found in the documentation for the Toggle Utility.
<!--{ @id Identifies the Menu for toggle targeting }-->
<!--{ @class Add "o-menu-fixed" in production layouts }-->
<aside class="o-menu block" id="aria-c-menu">
<div class="o-menu__wrap">
<!--{ @data-js "menu" Adds the toggling utility to close the menu }-->
<!--{ @data-js-menu "close" indicates that this is the primary closing button for the menu. Focus will shift from the open button to the close button when the menu is opened. }-->
<!--{ @aria-controls Targets the Menu ID for toggling }-->
<!--{ @aria-expanded Indicates the toggled state of the target }-->
<!--{ @tabindex Add tabindex="-1" to insure focusable elements are not visible when parent is hidden }-->
<button aria-controls="aria-c-menu" aria-expanded="true" class="o-menu__nav-item" data-js="menu" data-js-menu="close" tabindex="-1">
<!--{ @tabindex Add tabindex="-1" to insure focusable elements are not visible when parent is hidden }-->
<svg aria-hidden="true" class="icon icon-ui" tabindex="-1">
<use href="#feather-x"></use>
</svg>
<span>Close</span>
</button>
<hr />
<!--{ @data-js "themes" Adds the theme toggling utility to the theme button }-->
<!--{ @tabindex Add tabindex="-1" to insure focusable elements are not visible when parent is hidden }-->
<button class="o-menu__nav-item" data-js="themes" tabindex="-1">
<!--{ @tabindex Add tabindex="-1" to insure focusable elements are not visible when parent is hidden }-->
<svg aria-hidden="true" class="icon icon-ui" tabindex="-1">
<!--{ @data-js-themes "icon" lets the theme toggling utility where change the theme icon }-->
<use data-js-themes="icon" href="#feather-sun"></use>
</svg>
<span class="sr-only">Toggle </span>
<!--{ @data-js-themes "label" lets the theme toggling utility where to change the theme text label }-->
<span data-js-themes="label">Theme</span>
</button>
<hr />
<!--{ @aria-label Ensures landmarks are unique }-->
<nav aria-label="Menu" class="o-menu__nav">
<!--{ @tabindex Add tabindex="-1" to insure focusable elements are not visible when parent is hidden }-->
<a class="o-menu__nav-item " href="#" tabindex="-1">Menu</a>
</nav>
</div>
</aside>
The closing trigger should have the same attributes as the opening trigger, however, data-js-menu should be set to close. The closing trigger inside the menu should be placed towards the bottom of the menu to assist with thumb reach. Once the opening trigger is clicked focus will shift to the closing trigger and then the focus will be trapped inside the menu.
FAQs
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.