TableOfContents
Sticky sidebar navigation that tracks scroll position and highlights the active section. Hidden on mobile — DocsLayout provides the collapsible alternative there.
Playground
Introduction
Setup
Usage
<TableOfContents />01 Examples
Page navigation
Basic Usage
<TableOfContents
navigation={[
{ id: 'overview', title: 'Overview' },
{ id: 'api', title: 'API' }
]}
/>02 Accessibility
Named landmarks, because there are several
The component renders an <aside> holding one to three <nav> elements — sections, related pages, and the code toggle block. Every
one of them is labelled, because a documentation page already carries a handful of asides and
navigations and an unnamed one is a stop that announces nothing.
aria-current is location, not page
The active entry points at a section of the page the reader is already on, so it carries aria-current="location". page would claim it links to the current
document, which is what the sidebar's entry for this page does.
Scroll-spy marks, it does not move focus
Scrolling only changes which entry is marked. Focus stays where the reader left it — the alternative, dragging focus along with the scroll position, would make the page unusable with a keyboard.
Only the kickers are tagged with a language
"On this page", "Related" and the toggle label come from the docs translations and carry a lang of their own; the entry labels do not, because they are the page's section titles and are
written in the content language. Tagging the whole aside would declare those titles as the chrome
locale — a worse mismatch than the three kicker words it would fix.
Hidden below the sidebar breakpoint
The component is display-hidden on narrow viewports rather than reflowed, so it is out of
the reading order there as well as out of sight. DocsLayout renders its own collapsible
table of contents for that case — a page that uses this component standalone has to provide
the small-screen path itself.
03 API Reference
Complete list of component properties and their configurations
Prop | Type | Default | Description | |
|---|---|---|---|---|
navigation required | TocNavigationItem[] | — | Navigation items with optional nested children. | |
activeSection | string | — | Controlled active-section id. When provided (DocsLayout does this with
its layout-wide scrollspy), the TOC renders the active marker from it
and never starts its own scroll listener; leave undefined for
standalone use, where the TOC tracks scroll itself (trackScroll). | |
class | string | — | Extra classes merged onto the root aside element. | |
position variant | leftright | right | Controls the position behavior and appearance of the TableOfContents component. Available options: left, right. | |
related | RelatedLink[] | — | Optional Editorial // RELATED block rendered below the main nav.
Each entry needs a pre-resolved href (the TOC does not call
resolve(), mirroring the existing nav behaviour). When omitted,
the related block does not render at all. | |
showCodeToggle | boolean | true | Render the Editorial // CODE block at the bottom of the TOC,
hosting the global show-/hide-all-code toggle. Requires a host
page that provided a CodeVisibilityStore via context — the
block silently skips itself if no store is found, so callers
outside of DocsLayout don't have to know about it. | |
slotClasses | Partial<Record<TableOfContentsSlots, string>> | — | Per-slot class overrides. | |
title | string | — | Heading rendered above the nav links. Defaults to the localized "On this page". | |
trackScroll | boolean | — | Enable scroll-based active section tracking. | |
unstyled | boolean | — | Remove all default tv styles. | |
width variant | lgmdsm | md | Controls the width behavior and appearance of the TableOfContents component. Available options: lg, md, sm. | |
...TableOfContentsVariantProps variant | VariantProps | — | Styling variants from TableOfContentsVariantProps |
04 Types
Local type definitions used by this component.
Name | Kind | Category | Used by | Description | |
|---|---|---|---|---|---|
RelatedLink | interface | helper | 1 | — | |
TocNavigationItem | interface | helper | 1 | A single entry in the table of contents.
The list renders in array order. There is deliberately no order field: one
existed until 2026-08, was never read by anything, and 119 pages maintained
it — 660 entries — the Button reference page had drifted to api: 7 / installation: 6
while rendering them the other way round, and nobody noticed because nothing
sorts. Order the array; that is the order. | |
TableOfContentsProps | interface | props | 0 | Sticky sidebar navigation that tracks scroll position and highlights the active section. Hidden on mobile (DocsLayout provides a collapsible mobile alternative). | |
TableOfContentsVariantProps | type | variant | 1 | — | |
TableOfContentsSlots | type | variant | 0 | Slot names derived from the tv() config above — single source of truth for slotClasses. |
05 Installation
Import
import { TableOfContents } from '@urbicon-ui/docs';