The m3e-nav-menu component is a hierarchical menu optimized for sidebars and drawers on larger
devices. It enables users to explore nested menu structures and seamlessly switch between application views.
npm i @m3e/nav-menu
This section outlines usage examples and configuration guidance for the components in this package.
Use the m3e-nav-menu and m3e-nav-menu-item to create a multilevel navigation menu.
Use the label slot of a m3e-nav-menu-item to specify an item's label. In addition, use
the icon slot to include an icon before the item's label and use the badge slot to
specify to specify a compact status indicator or supplementary text.
To create multiple levels, nest one or more m3e-nav-menu-item components.
<m3e-nav-menu>
<m3e-nav-menu-item open>
<m3e-icon slot="icon" name="rocket_launch" aria-hidden="true"></m3e-icon>
<span slot="label">Getting Started</span>
<m3e-nav-menu-item>
<m3e-icon slot="icon" name="widgets" aria-hidden="true"></m3e-icon>
<span slot="label">Overview</span>
</m3e-nav-menu-item>
<!-- Additional items omitted for brevity -->;
</m3e-nav-menu-item>
<m3e-nav-menu-item>
<span slot="label">Actions</span>
<!-- Items omitted for brevity -->;
</m3e-nav-menu-item>
</m3e-nav-menu>
You can use a m3e-nav-menu-item-group to group top-level items in a menu. Use the
label slot to specify a group's label. Use a m3e-divider to separate groups in a menu.
See Divider for more information.
<m3e-nav-menu>
<m3e-nav-menu-item-group>
<m3e-heading slot="label" variant="label" size="large">Mail</m3e-heading>
<m3e-nav-menu-item>
<m3e-icon slot="icon" name="mail"></m3e-icon>
<span slot="label">Inbox</span>
<span slot="badge">24</span>
</m3e-nav-menu-item>
<!-- Additional items omitted for brevity -->
</m3e-nav-menu-item-group>
<m3e-divider></m3e-divider>
<m3e-nav-menu-item-group>
<m3e-heading slot="label" variant="label" size="large">Personal folders</m3e-heading>
<!-- Items omitted for brevity -->;
</m3e-nav-menu-item-group>
</m3e-nav-menu>
Use the disabled attribute of a m3e-nav-menu-item to disable the item and any
children. Disabling an item with children will not automatically close it.
<m3e-nav-menu>
<m3e-nav-menu-item open disabled>
<m3e-icon slot="icon" name="rocket_launch" aria-hidden="true"></m3e-icon>
<span slot="label">Getting Started</span>
<m3e-nav-menu-item>
<m3e-icon slot="icon" name="widgets" aria-hidden="true"></m3e-icon>
<span slot="label">Overview</span>
</m3e-nav-menu-item>
<!-- Additional items omitted for brevity -->;
</m3e-nav-menu-item>
<m3e-nav-menu-item open>
<span slot="label">Actions</span>
<m3e-nav-menu-item disabled><span slot="label">Button</span></m3e-nav-menu-item>
<!-- Additional items omitted for brevity -->;
</m3e-nav-menu-item>
</m3e-nav-menu>
Nav menus are given ARIA role="tree", and items are assigned role="treeitem",
indicating a structured, hierarchical navigation model that supports keyboard interaction, semantic grouping,
and accessible labeling. Expandable items use aria-expanded to indicate visibility of nested
content, and current items may use aria-current to signal the active page or view.
Focus is managed on the m3e-nav-menu container using tabindex="0", and the currently
active item is referenced via aria-activedescendant, which points to the ID of the focused
m3e-nav-menu-item. This enables roving focus without shifting DOM focus, ensuring accessible
keyboard navigation and consistent screen reader feedback.
Groups are given ARIA role="group", indicating that their contents form a semantic unit within the
navigation tree and are labeled by the content of the group's label slot.
Icons and dividers are given aria-hidden="true" ensure they're treated as purely decorative and
excluded from the accessibility tree.
Disabling an item sets aria-disabled="true" signaling to assistive technologies that the item is
not interactive.
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/nav-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"
}
}
</script>
For production, use index.min.js and a11y.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.