The m3e-toc component generates a hierarchical table of contents for in-page navigation.
npm i @m3e/toc
This section outlines usage examples and configuration guidance for the components in this package.
The m3e-toc component automatically generates a table of contents by scanning heading elements
(h1 through h6, and m3e-hading) within a specified container. It creates
a navigable outline that reflects the document's structure, enabling users to quickly jump between sections.
To activate, set the for attribute to the ID of the container whose headings should be indexed. The
generated TOC updates reactively as headings are added, removed, or reordered.
Headers having the m3e-toc-ignore attribute will be ignored by the TOC generator. This is typically
used for page-level headings whose text is mirrored by the TOC's title.
<div id="d1">
<m3e-toc for="d1">
<span slot="overline">Overline</span>
<span slot="title">Title</span>
</m3e-toc>
<div>
<h2 id="h1">Heading 1</h2>
<h3 id="h1.1">Heading 1.1</h3>
<h4 id="h1.1.1">Heading 1.1.1</h4>
<h3 id="h2">Heading 1.2</h3>
<h2 id="h2.1">Heading 2</h2>
</div>
</div>
Use the overline and title slots to provide heading content for a TOC. The overline is
limited to a single line and the title is limited to two lines. If content overflows, it will be truncated with
an ellipsis.
<m3e-toc for="d1">
<span slot="overline">Overline</span>
<span slot="title">Title</span>
</m3e-toc>
When generating a TOC, you can control the maximum depth of headers that appear in the TOC using the
max-depth attribute. By default, the maximum depth is 2.
The heading depth is determined by the highest-level heading found within the container. For example, if no
h1 is present but an h2 is, the depth starts at level 2.
The m3e-toc component is marked with role="navigation" to signal its purpose as a
navigational landmark.
To ensure assistive technologies announce it meaningfully, TOCs should labeled using both the overline and title
via aria-labelledby. This dual-labeling approach preserves expressive hierarchy—where the overline
provides contextual framing (e.g., “On this page”) and the title conveys specific content.
Individual items are organized within an unordered list and given ARIA role="link" to convey their
interactive nature to assistive technologies. Each item also receives tabindex="-1" to make it
programmatically focusable without being included in the default tab order.
The active item receives aria-current="true" to indicate its current state within the document
context. This attribute helps assistive technologies convey that the linked section is currently in view,
enhancing orientation and navigational clarity for screen reader users.
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/toc/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.