On this page Menu Menu

The m3e-menu component presents a list of choices on a temporary surface, typically anchored to a trigger element.

Installation
npm i @m3e/menu
Usage

This section outlines usage examples and configuration guidance for the components in this package.

Basic usage

The m3e-menu is used in conjunction with a m3e-menu-trigger to create a menu opened when the parenting element of the trigger is activated. Use the for attribute of the m3e-menu-trigger to designate the menu to open.

Menu Item 1 Item 2
<m3e-button>
  <m3e-menu-trigger for="menu1">Menu</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu1">
  <m3e-menu-item>Item 1</m3e-menu-item>
  <m3e-menu-item>Item 2</m3e-menu-item>
</m3e-menu>
Menu items

The <m3e-menu> component supports three distinct types of menu items, each tailored for different interaction patterns and semantic roles:

Icons

All menu item types provide two named slots for icons. Use the icon slot to present an icon before an item's label and use the trailing-icon slot to present an icon after it.

Menu items with icons Redial Check voice mail Disable alerts
<m3e-button>
  <m3e-menu-trigger for="menu8">Menu items with icons</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu8">
  <m3e-menu-item>
    <m3e-icon slot="icon" name="dialpad"></m3e-icon>
    Redial
  </m3e-menu-item>
  <m3e-menu-item>
    <m3e-icon slot="icon" name="voicemail"></m3e-icon>
    Check voice mail
  </m3e-menu-item>
  <m3e-menu-item>
    <m3e-icon slot="icon" name="notifications_off"></m3e-icon>
    Disable alerts
  </m3e-menu-item>
</m3e-menu>
        
Disabling

Use the disabled attribute to disable a menu item.

Menu with disabled items Redial Check voice mail Disable alerts
<!-- Trigger omitted for brevity -->
<m3e-menu id="menu8">
  <m3e-menu-item disabled>
    <m3e-icon slot="icon" name="dialpad"></m3e-icon>
    Redial
  </m3e-menu-item>
  <!-- Additional items omitted for brevity -->
</m3e-menu>
        
Checkboxes

Use a m3e-menu-item-checkbox to present a toggleable menu item that supports multi-select. The checked attribute reflects the checked state of the menu item. If a menu item specifies an icon using the icon slot, it will be replaced with a check icon when checked.

Menu with checkboxes Bold Italic Underline
<m3e-button>
  <m3e-menu-trigger for="menu2">Menu with checkboxes</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu2">
  <m3e-menu-item-checkbox checked>
    <m3e-icon slot="icon" name="format_bold"></m3e-icon>
    Bold
  </m3e-menu-item-checkbox>
  <m3e-menu-item-checkbox>
    <m3e-icon slot="icon" name="format_italic"></m3e-icon>
    Italic
  </m3e-menu-item-checkbox>
  <m3e-menu-item-checkbox>
    <m3e-icon slot="icon" name="format_underlined"></m3e-icon>
    Underline
  </m3e-menu-item-checkbox>
</m3e-menu>
Radios

Use a m3e-menu-item-radio to present a toggleable menu item that supports single-select. The checked attribute reflects the checked state of the menu item. If a menu item specifies an icon using the icon slot, it will be replaced with a check icon when checked.

Menu with radios Ascending Descending
<m3e-button>
  <m3e-menu-trigger for="menu3">Menu with radios</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu3">
  <m3e-menu-item-radio checked>Ascending</m3e-menu-item-radio>
  <m3e-menu-item-radio>Descending</m3e-menu-item-radio>
</m3e-menu>

Use a m3e-menu-item-group to organize multiple sets of radio items within a single m3e-menu. Each group maintains its own selection state, allowing distinct radio groups to coexist independently.

Menu with radio groups Ascending Descending Alphabetical By Date
<m3e-button>
  <m3e-menu-trigger for="menu4">Menu with radio groups</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu4">
  <m3e-menu-item-group>
    <m3e-menu-item-radio checked>Ascending</m3e-menu-item-radio>
    <m3e-menu-item-radio>Descending</m3e-menu-item-radio>
  </m3e-menu-item-group>
  <m3e-divider></m3e-divider>
  <m3e-menu-item-group>
    <m3e-menu-item-radio checked>Alphabetical</m3e-menu-item-radio>
    <m3e-menu-item-radio>By Date</m3e-menu-item-radio>
  </m3e-menu-item-group>
</m3e-menu>
Submenus

Submenus are triggered by nesting a m3e-menu-trigger in a m3e-menu-item and designating the submenu to open using the for attribute.

Menu with submenus Fruits with A Grapes Olive Orange Apricot Avocado Apples Fuji Granny Smith Red Delicious
<m3e-button>
  <m3e-menu-trigger for="menu5">Menu with submenus</m3e-menu-trigger>
</m3e-button>
<m3e-menu id="menu5">
  <m3e-menu-item>
    <m3e-menu-trigger for="menu6">Fruits with A</m3e-menu-trigger>
  </m3e-menu-item>
  <m3e-menu-item>Grapes</m3e-menu-item>
  <m3e-menu-item>Olive</m3e-menu-item>
  <m3e-menu-item>Orange</m3e-menu-item>
</m3e-menu>
<m3e-menu id="menu6">
  <m3e-menu-item>Apricot</m3e-menu-item>
  <m3e-menu-item>Avocado</m3e-menu-item>
  <m3e-menu-item>
    <m3e-menu-trigger for="menu7">Apples</m3e-menu-trigger>
  </m3e-menu-item>
</m3e-menu>
<m3e-menu id="menu7">
  <m3e-menu-item>Fuji</m3e-menu-item>
  <m3e-menu-item>Granny Smith</m3e-menu-item>
  <m3e-menu-item>Red Delicious</m3e-menu-item>
</m3e-menu>
Accessibility

Menus are given the ARIA role="menu", indicating that the serve as a container for a list of interactive menu items.

Triggers augment their parenting elements with aria-haspopup, aria-controls, and aria-expanded to create a relationship with the trigger's menu.

When a menu is opened, the focus is set to the first enabled menu item. On close, focus is returned to the trigger.

Standard menu items are given ARIA role="menuitem", checkboxes are given role="menuitemcheckbox", and radios are given role="menuitemradio". The aria-checked attribute reflects the checked state of an item.

Disabled menu items are given aria-disabled="true" in order to convey to assistive technologies that the item is disabled. In addition, tabindex is removed to indicate the item is no longer focusable.

Menu item groups are given ARIA role="group" and should be labelled using aria-label or aria-labelledby.

Native module support

This package uses JavaScript Modules. To use it directly in a browser without a bundler, use a module script similar to the following.

<script type="module" src="/node_modules/@m3e/menu/dist/index.js"></script>

In addition, you must use an import map to include dependencies.

<script type="importmap">
  {
    "imports": {
      "lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
      "@m3e/core": "/node_modules/@m3e/core/dist/index.js",
      "@m3e/core/a11y": "/node_modules/@m3e/core/dist/a11y.js",
      "@m3e/core/anchoring": "/node_modules/@m3e/core/dist/anchoring.js"
    }
  }
</script>

For production, use index.min.js, a11y.min.js, and anchoring.min.js for faster load times.

API

This package includes a Custom Elements Manifest (custom-elements.json), which documents the properties, attributes, slots, events and CSS custom properties of each component.

You can explore the API below, or integrate the manifest into your own tooling.