The m3e-menu component presents a list of choices on a temporary surface, typically anchored to a
trigger element.
npm i @m3e/menu
This section outlines usage examples and configuration guidance for the components in this package.
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.
<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>
The <m3e-menu> component supports three distinct types of menu items, each tailored for
different interaction patterns and semantic roles:
m3e-menu-item — A standard menu item typically used for navigation or triggering commands.m3e-menu-item-checkbox — A toggleable menu item option used for multi-select scenarios.m3e-menu-item-radio — A toggleable menu item option used for single-select scenarios.
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.
<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>
Use the disabled attribute to disable a menu item.
<!-- 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>
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.
<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>
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.
<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.
<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 are triggered by nesting a m3e-menu-trigger in a m3e-menu-item and
designating the submenu to open using the for attribute.
<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>
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.
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.
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.