npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@barrierefrei/a11y-menu-2

v1.2.0

Published

A fully accessible menu

Downloads

8

Readme

a11y-menu-2

A menu that is fully accessible. It has no design or theme applied. That way you can be certain the menu is usable and accessible and you can apply your own styles.

Pipeline status npm

The code is based on the recommendations made by the W3C and has some extra features.

Key features:


Table of contents

Requirements

  • You need to be able to import JavaScript files
  • Valid HTML structure for a navigation (see Example)

Changelog

See changelog.md.

Install

npm i @barrierefrei/a11y-menu-2

Usage

HTML

The following example contains all nessessary attributes like aria-expanded, aria-controls, inert and aria-label.

HTML example file: docs/markup.html

The script will automatically add the aria-current="page" attribute to any link, that matches the current URL. It will also add data-current-parent to any parent HTMLLiElements.

JavaScript

import { A11yMenu2 } from '@barrierefrei/a11y-menu-2';

const myMenu = new A11yMenu2({
  nav: document.querySelector('nav'),
});

You can also call a method closeAll to close all menu items. You could run this on any Event.:

/** Close all menu item on a button click */
document.getElementById('close')?.addEventListener('click', () => {
  myMenu.closeAll();
});

Also check out Events.

Parameters

See ParameterOptions in src/index.ts.

State changes

State changes are mapped with ARIA.

Buttons that control submenus will change their aria-expanded attribute and the inert attribute of the associated submenu.

Example of a collapsed submenu:

<button aria-expanded="false" aria-controls="submenu">Toggle</button>
<div id="submenu" inert>Submenu</div>

Example of an expanded submenu:

<button aria-expanded="true" aria-controls="submenu">Toggle</button>
<div id="submenu">Submenu</div>

Events

Some custom events will be fired. Checkout all available events at src/_events.ts

const myMenu = new A11yMenu2({ ... })

myMenu.onEvent('onSubmenuOpen', (options) => {
  console.log('A submenu was opened', options);
  console.log('The trigger is:', options.currentTrigger);
  console.log('The submenu is:', options.currentSubmenu);
  console.log('The navigation is:', options.nav);
})

Keyboard support

| Key | Function | | ----------------- | --------------------------------------------------------------------------------------------------------------- | | Tab / Shift + Tab | Move keyboard focus among top-level buttons and if a submenu is open, into and through links in the submenu. | | Escape | If a submenu is open, closes it and sets focus on the button that controls that submenu. | | Home | If focus is on a link/button, and it is not the first link/button, moves focus to the first link/button (toplevel). | | End | If focus is on a link/button, and it is not the last link/button, moves focus to the last link/button (toplevel). | |Space or Enter|If focus is on a button that triggers a submenu, activates the button, which toggles the visibility of the submenu (inert). If focus is on a link: 1.) If any link has aria-current set, removes it. 2.) Sets aria-current="page" on the focused link. 3.) Activates the focused link (aria-expanded="true").|

Styles

The menu does not come with any design or theme applied.

Selectors

To apply styles for different states, use these CSS selectors:

CSS example file: docs/selectors.css

Motivation

This 📦 package is a variant of another accessible menu. While you can navigate @wanjapflueger/a11y-menu with the arrow keys, this 📦 package @barrierefrei/a11y-menu-2 can be navigated with the tab keys.

The reason for this is, that with @wanjapflueger/a11y-menu complex HTML that is not part of the menu structure will break the code, because it relies on a perfekt structure.

This approach is more open. The HTML may contains unordered lists <ul> that do not contain any menu items. You can even include heading tags like <h2> or images <img> or use a <div> as a submenu item.

In this approach you set a few required HTML-Attributes manually, allowing you to use anchorlinks <a>, lists <ul>, <li> and other tags inside of the surrounding navigation <nav> that are not part of the very same.

In the examples below we compare @wanjapflueger/a11y-menu and @barrierefrei/a11y-menu-2.

Example A) Simple structure with no extra HTML. Every element is part of the menu structure.

| @wanjapflueger/a11y-menu | @barrierefrei/a11y-menu-2 | | ------------------------ | ------------------------- | | ✅ Supported | ✅ Supported |

<nav>
  <ul>
    <li>
      <span>Colors</span>
      <ul>
        <li>
          <a href="/colors/red">Red</a>
          <a href="/colors/blue">Blue</a>
        </li>
      </ul>
    </li>
  </ul>
</nav>

Example B) In this example we add a <div class="info"> with a <h2> and a link <a>, that is not a menu item. Those elements do nothing for the menu functionality.

| @wanjapflueger/a11y-menu | @barrierefrei/a11y-menu-2 | | ---------------------------------------------------------- | ------------------------- | | ❌ Not supported. Additional HTML elements break the menu. | ✅ Supported |

<nav>
  <ul>
    <li>
      <div class="info">
        <h2>Colors</h2>
        <a href="/colors">Read more about colors</a>

        <ul>
          <li>
            <a href="/colors/red">Red</a>
            <a href="/colors/blue">Blue</a>
          </li>
        </ul>
      </div>
    </li>
  </ul>
</nav>

Accessibility Compliance Report

WCAG Level: AA [^1]

| Browser | Platform | Screen reader | Passed | | ------------------ | ---------- | ----------------------------------------------------------------------------------------------------------------------- | ------ | | Chrome 115 | MacOS 13.0 | VoiceOver | ✅ | | Chrome 115 | Windows 11 | Narrator | ✅ | | Chrome 115 | Android 10 | TalkBack | ✅ | | Firefox 116 | MacOS 13.0 | VoiceOver | ✅ | | Safari 16.1 | MacOS 13.0 | VoiceOver | ✅ | | Microsoft Edge 115 | MacOS 13.0 | VoiceOver | ✅ | | Microsoft Edge 115 | Windows 11 | Narrator | ✅ |


[^1]: This information refers only to the technical aspects of the component, not to the design or the editorial handling of any content.