Preview
Installation
Basic usage
The full view shows every accepted heading with native anchors. Branches have no disclosure arrows by default. Set collapsible to enable independent branch controls. The caller owns heading discovery, scroll observation, hash updates, and focus. The compact selector calls onNavigate after a choice, while modified clicks keep native browser behavior.
Structure
Examples
Nested tree
Show the full heading hierarchy without collapse controls.
Compact selector
At tablet widths and below, the section selector uses ghost styling with a progress clock inside the leading edge of its trigger. Set responsive={false} to use this compact layout in an embedded narrow host at any viewport width.
Hidden compact mode
Depth-limited and collapsible
Enable collapsible to let readers hide nested headings. Heading labels keep their native navigation action.
API reference
readingProgress accepts a fraction from 0 to 1 supplied by the caller. It fills the compact clock. The desktop rail highlights only the active heading, starting at that heading’s row. The compact clock has no numeric counter. Scroll observation belongs to the consuming page. The heading list uses 12 px text at every depth.
| Prop | Type | Default | Description |
|---|---|---|---|
readingProgress | number | undefined | Reading fraction from 0 to 1. Drives the compact reading clock; activeId controls the rail segment. | |
items | TableOfContentsItem[] | undefined | Heading items with stable IDs, labels, optional depth, and optional href. | |
activeId | string | undefined | Controlled heading ID shown as active. | |
onNavigate | ((id: string, event?: React.MouseEvent<HTMLAnchorElement>) => void) | undefined | Called for ordinary anchor activation and compact selection. | |
collapsible | boolean | false | Enables branch arrows and expansion state. Without it, every heading remains visible. |
maxDepth | number | undefined | 6 | Bounds accepted heading depth to 2 through 6. |
defaultExpandedIds | string[] | undefined | Initial expanded branch IDs when collapsible is enabled. | |
expandedIds | string[] | undefined | Controlled expanded branch IDs when collapsible is enabled. | |
onExpandedIdsChange | ((ids: string[]) => void) | undefined | Receives disclosure changes. | |
compact | "select" | "hidden" | "tree" | undefined | "select" | Chooses the presentation at tablet widths and below. Desktop keeps the full tree by default. |
responsive | boolean | true | Use the tablet breakpoint. Set false to force a compact selector in a narrow embedded host. |
label | string | undefined | "On this page" | Visible and accessible name for the page index. |
stickyOffset | number | string | undefined | Optional sticky top offset. | |
className | string | undefined | Adds a class to the composition root. |