Skip to content
Protocore Design Systemv1.6.9

/// Navigation

TableOfContents

A page nav auto-built from headings, with scrollspy active-highlighting — the reusable docs rail.

import { TableOfContents } from "@protocore/pds";
View as Markdown

Explicit headings

Pass a headings array of { id, text, level }. Each renders as a real anchor to #id, indented by level. As the reader scrolls, the entry for the section in view highlights via scrollspy.

Overview

Section content for overview. Scroll the page to watch the rail track the heading in view.

Installation

Section content for installation. Scroll the page to watch the rail track the heading in view.

Configuration

Section content for configuration. Scroll the page to watch the rail track the heading in view.

Deploying

Section content for deploying. Scroll the page to watch the rail track the heading in view.

Scanning the DOM

Omit headings and the component scans the page for you: give it a containerSelector (default "main") and a selector (default "h2, h3"), and it collects every matching heading that has an id. This is the mode to pair with Prose — render your CMS/markdown content (whose headings already carry slugged ids), drop a TableOfContents beside it, and the rail builds itself.

The anchors are ordinary links, so the rail works with JavaScript disabled; the IntersectionObserver only drives the active-highlight. Clicking smooth-scrolls to the target and moves keyboard focus there. Tune offset to match any sticky header so the active section flips at the right moment.

Usage

Do

  • Ensure every target heading has a stable `id` to anchor to.
  • Use scan mode next to Prose-rendered content.
  • Set `offset` to your sticky-header height for accurate spy timing.
  • Keep it to two levels (h2/h3) so the rail stays scannable.

Don't

  • Point entries at headings without ids; the anchor has nowhere to go.
  • Nest four-plus levels; the rail becomes a thicket.
  • Rebuild it from scroll math — it already uses an observer.

Accessibility

KeysAction
TabMoves through the table-of-contents links
EnterJumps to the section and moves focus there
  • Renders a `<nav>` landmark with an `aria-label`, and marks the active entry with `aria-current="location"`.
  • Activating a link moves keyboard focus to the target heading (via a temporary `tabindex`), so the next Tab continues from the new section.

TableOfContents props

PropTypeDefaultDescription
classNamestring
containerSelectorstringmainCSS selector for the region to scan.
headingsTocHeading[]Explicit headings. Omit to scan the DOM via `containerSelector` + `selector`.
labelstringTable of contentsAccessible name for the nav landmark.
offsetnumber96Distance (px) from the top at which a heading becomes active.
selectorstringh2, h3Which headings to collect when scanning.
styleCSSProperties

Related

  • NavLinkNavigation link row for sidebars and menus — leading icon, label, optional description and trailing count/chevron, an inked active row with a 2px accent leading rule, and collapsible nested sub-links.
  • BreadcrumbBreadcrumb trail — a mono UPPERCASE, "/"-separated path where crumbs are links and the last is the inked current page.
  • ProseA typographic wrapper that styles raw rendered HTML (CMS/markdown output) with the PDS type scale and rhythm.
  • SidebarA left navigation rail of grouped items — mono uppercase group labels over sans links, with an accent rule on the active item.