@wanjapflueger/a11y-menu
TypeScript icon, indicating that this package has built-in type declarations

2.5.2 • Public • Published

a11y-menu

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 npm bundle size


Table of contents


Requirements

Changelog

See changelog.md.

Install

npm i @wanjapflueger/a11y-menu

Example

example.barrierefrei.kiwi/a11y-menu/

Usage

Init

Import class Menu.

import { Menu } from '@wanjapflueger/a11y-menu';
// var a11yMenu = require("@wanjapflueger/a11y-menu")

Create a new instance

const myMenu = new Menu();
// const myMenu = new a11yMenu.Menu();

Methods

Method Create

  1. Create a navigation of this simple structure.

    <nav>
      <ul>
        <li><a href="/">Home</a></li>
        <li>
          <span>Topics</span>
          <ul>
            <li><a href="/dogs">Dogs</a></li>
            <li><a href="/cats">Cats</a></li>
            <li><a href="/birds">Birds</a></li>
          </ul>
        </li>
        <li><a href="/contact">Contact</a></li>
        <li><a href="/privacy">Privacy</a></li>
      </ul>
    </nav>

    Important:

    • Each HTMLLIElement including a direct child (HTMLUListElement, submenu) HTMLSpanElement.

    • It is not possible to create a link on a HTMLLIElement that includes a direct child (HTMLUListElement, submenu)

      <!-- ✅ Do -->
      <li>
        <span>Topics</span>
        <ul>
          <li><a href="/dogs">Dogs</a></li>
          <li>...</li>
        </ul>
      </li>
      
      <!-- ❌ Do not -->
      <li>
        <a href="/topics">Topics</a>
        <ul>
          <li><a href="/dogs">Dogs</a></li>
          <li>...</li>
        </ul>
      </li>
  2. Assign that navigation element with JavaScript to a variable, initiate a new instance of Menu and call method Create.

    import { Menu } from '@wanjapflueger/a11y-menu';
    
    const myMenu = new Menu();
    myMenu.Create({
      nav: document.querySelector('nav'),
    });
Parameters

See MenuParameters in src/index.ts.

Name Required Type Default value Description Example
nav ✅ Yes HTMLElement Navigation element. Any HTMLElement being a <nav> element. <nav>...</nav>
config ❌ No Config undefined Menu configuration. { responsive: [{minWidth: 768, config: [{closeOnNavigate: true, direction: 'x', level: 0}]}] }

Config

import { Menu } from '@wanjapflueger/a11y-menu';

const myMenu = new Menu();
myMenu.Create({
  nav: document.querySelector('nav'),
  config: {
    breakpoints: [
      {
        minWidth: 0,
        config: [
          {
            closeOnNavigate: false,
            level: 0,
          },
        ],
      },
      {
        minWidth: 768,
        config: [
          {
            closeOnNavigate: false,
            closeOnClick: true,
            direction: 'vertical',
            level: 0,
          },
        ],
      },
      {
        minWidth: 1280,
        config: [
          {
            direction: 'horizontal',
            level: 0,
          },
          {
            direction: 'vertical',
            level: 1,
          },
        ],
      },
    ],
  },
});

This would mean:

  1. On screens bigger than 768px and smaller than 1280px...

    1. on MenuItem.level === 0 use the up- and down arrow keys to go to the next MenuItem
  2. On screens bigger than 1280px...

    1. On MenuItem.level === 0 use the left- and right keys to go to the next MenuItem

    2. On MenuItem.level === 1 use the up- and down keys to go to the next MenuItem

The default value for direction is always 'vertical'.

Styles

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

Selectors

To apply styles for different states, use these selectors:

[role='menubar'] {
  /** Top level menu */
}

[role='menu'] {
  /** Sub menus */
}

[role='none'] {
  /** Menu item parent with no function. Only when the [role='menuitem'] is an anchorlink element */
}

a[role='menuitem'] {
  /** Menu item that is clickable */
}

li[role='menuitem'] {
  /** Menu item that contains a submenu ([role="menu"]) */
}

[role='menuitem'][aria-expanded='true'] {
  /** Menu items that are expanded */
}

[role='menuitem'][data-focus='true'] {
  /** The menu item that has the focus */
}

[role='menuitem'][aria-current='page'] {
  /** Menu items that match the current page */
}

[role='menuitem'][data-current-parent='true'] {
  /** Menu items that are parents of the [aria-current="page"] */
}

[role='menuitem'][data-level='{number}'] {
  /** The depth level of a menu item (replace `{number}` with a number, starting with `0`) */
}

Example Styles

Here are some example styles.

ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}

[role='menubar'] {
  display: flex;
}

[role='menuitem'] {
  position: relative;
  background-color: #ccc;
  min-width: 100px;
  display: block;
  cursor: pointer;
  padding: 5px 10px;
}

[role='menuitem']:hover,
[role='menuitem']:focus-visible {
  text-decoration: underline;
}

[role='menuitem'] > ul {
  position: absolute;
}

[aria-expanded='false']::before {
  content: '→';
}
[aria-expanded='true']::before {
  content: '↓';
}

[aria-expanded='false'] > ul {
  display: none;
}

nav > ul > li > ul > li ul {
  left: 100%;
  top: 0;
  outline: 1px solid red;
}

Keyboard support

In index.ts at menuItemControls several keys have been assigned a function. The keyboard support starts when any element in the menu is active. A menu is active when:

  • any nav [role="menuitem"] is focussed
Key Description
ArrowRight Next or submenu (direction === 'horizontal')
ArrowDown Next or submenu (direction === 'vertical')
ArrowLeft Previous or parent (direction === 'horizontal')
ArrowUp Previous or parent (direction === 'vertical')

Accessibility Compliance Report

WCAG Level: AAA 1

Browser Platform Screen reader Passed
Chrome 95 Windows 10 NVDA
Firefox 93 Windows 10 NVDA
Microsoft Edge 95 Windows 10 NVDA
Chrome 94 Android 10 TalkBack
Chrome 95 MacOS 11.15.2 VoiceOver
Firefox 90 MacOS 11.15.2 VoiceOver
Microsoft Edge 95 MacOS 11.15.2 VoiceOver

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

Package Sidebar

Install

npm i @wanjapflueger/a11y-menu

Weekly Downloads

2

Version

2.5.2

License

ISC

Unpacked Size

53.3 kB

Total Files

6

Last publish

Collaborators

  • wanjapflueger