Table of Contents
A navigation component that tracks and highlights the active section as users scroll through document content.
Anatomy
<Toc.Root items={items} scrollEl={() => scrollContainer}>
<Toc.Content />
<Toc.Nav>
<Toc.Title />
<Toc.List>
<Toc.Indicator />
<Toc.Item item={item}>
<Toc.Link />
</Toc.Item>
</Toc.List>
</Toc.Nav>
</Toc.Root>
Examples
Basic
Pass headings to items, and point scrollEl at the scrollable container so the TOC knows what to track.
Nested Headings
Read depth in your own markup to indent sub-headings. Nothing is indented for you.
Root Provider
Use useToc with Toc.RootProvider to reach activeIds from outside the tree, so other parts of your UI can follow
the reading position.
With Collapsible
Wrap Toc.Nav in a Collapsible to let users hide the navigation. Toc.Context exposes activeItems, here driving a
progress ring.
With Hover
Expand the navigation on onMouseEnter and collapse it on onMouseLeave, with a pin toggle to keep it open.
Note: Hover does not exist on touch screens. Pair this with a pin button or a disclosure control so the navigation stays reachable on mobile.
With Indicator
Add Toc.Indicator inside Toc.List for a marker that slides to the active item.
With Rail
Give each item a small SVG offset by depth. Where neighbouring items sit at different depths, a bezier joins the two
positions so the rail steps rather than breaks.
With Tree View
Pair Toc.Root with TreeView for hierarchical navigation. onActiveChange expands the branch holding the active
heading.
Guides
Items
Every entry needs value, the id of the heading element, and depth, the heading level.
const items = [
{ value: 'introduction', depth: 2 },
{ value: 'installation', depth: 2 },
{ value: 'peer-dependencies', depth: 3 },
]
value must match the heading's id exactly. The component resolves it with getElementById to track visibility, and
Toc.Link targets it with href="#introduction". An item whose id is missing renders but never activates.
Ids are global to the page, so prefix them when a page holds more than one TOC.
Extra properties are fine, a label for link text being the common one. TocItemData covers only value and depth,
so extend it rather than annotating with it directly:
import type { TocItemData } from '@ark-ui/react/toc'
interface Item extends TocItemData {
label: string
}
API Reference
Props
Root
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
items | TocItem[]The TOC items with `value` (slug/id) and `depth` (heading level). | |
activeIds | string[]The controlled active heading ids. | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
autoScroll | true | booleanWhether to auto-scroll the TOC container so the first active item is visible when active headings change. |
defaultActiveIds | string[]The default active heading ids when rendered. Use when you don't need to control the active headings. | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
title: string
list: string
item: (value: string) => string
link: (value: string) => string
indicator: string
}>The ids of the elements in the TOC. Useful for composition. | |
onActiveChange | (details: ActiveChangeDetails) => voidCallback when the active (visible) headings change. | |
rootMargin | '-20px 0px -40% 0px' | stringThe root margin for the IntersectionObserver. Controls the effective viewport area for determining active headings. |
scrollBehavior | 'smooth' | ScrollBehaviorThe default scroll behavior used when auto-scrolling the TOC container and when scrolling to a heading (via link click or `api.scrollTo`). Can be overridden per-call by passing `behavior` to `api.scrollTo`. |
scrollEl | () => HTMLElement | nullFunction that returns the scroll container element to observe within. Defaults to the document/viewport. | |
threshold | 0 | number | number[]The IntersectionObserver threshold. A value of `0` means the heading is active as soon as even one pixel is visible within the root margin area. |
| CSS Variable | Description |
|---|---|
--top | The top position value |
--left | The left position value |
--width | The width of the element |
--height | The height of the element |
Content
Renders a <> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Indicator
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Item
Renders a <li> element.
| Prop | Default | Type |
|---|---|---|
item | TocItemThe TOC item | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | toc |
[data-part] | item |
[data-value] | The value of the item |
[data-depth] | The depth of the item |
[data-active] | Present when active or pressed |
[data-first] | |
[data-last] |
| CSS Variable | Description |
|---|---|
--depth | The depth value for the Item |
Link
Renders a <a> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Attribute | Description |
|---|---|
[data-scope] | toc |
[data-part] | link |
[data-value] | The value of the item |
[data-active] | Present when active or pressed |
List
Renders a <ul> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Nav
Renders a <> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
placement | 'left' | 'right' |
RootProvider
Renders a <div> element.
| Prop | Default | Type |
|---|---|---|
value | UseTocReturn | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Title
Renders a <h2> element.
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Context
API
| Property | Type |
|---|---|
activeIds | string[]All currently active (visible) heading ids |
activeItems | TocItem[]The active (visible) TOC items |
items | TocItem[]The resolved items list |
setActiveIds | (value: string[]) => voidManually set the active heading ids |
scrollTo | (value: string, details?: ScrollToDetails | undefined) => voidScrolls to the heading with the given id. |
getItemState | (props: ItemProps) => ItemStateReturns the state of a TOC item |