Components
Toc

Table of Contents

A navigation component that tracks and highlights the active section as users scroll through document content.

Loading...

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.

PropDefaultType
items
TocItem[]

The TOC items with `value` (slug/id) and `depth` (heading level).

activeIds
string[]

The controlled active heading ids.

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
autoScrolltrue
boolean

Whether 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
string

The 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) => void

Callback when the active (visible) headings change.

rootMargin'-20px 0px -40% 0px'
string

The root margin for the IntersectionObserver. Controls the effective viewport area for determining active headings.

scrollBehavior'smooth'
ScrollBehavior

The 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 | null

Function that returns the scroll container element to observe within. Defaults to the document/viewport.

threshold0
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 VariableDescription
--topThe top position value
--leftThe left position value
--widthThe width of the element
--heightThe height of the element

Content

Renders a <> element.

PropDefaultType
asChild
boolean

Use 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.

PropDefaultType
asChild
boolean

Use 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.

PropDefaultType
item
TocItem

The TOC item

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[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 VariableDescription
--depthThe depth value for the Item

Link

Renders a <a> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[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.

PropDefaultType
asChild
boolean

Use 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.

PropDefaultType
asChild
boolean

Use 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.

PropDefaultType
value
UseTocReturn

asChild
boolean

Use 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.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Context

API

PropertyType
activeIds
string[]

All currently active (visible) heading ids

activeItems
TocItem[]

The active (visible) TOC items

items
TocItem[]

The resolved items list

setActiveIds
(value: string[]) => void

Manually set the active heading ids

scrollTo
(value: string, details?: ScrollToDetails | undefined) => void

Scrolls to the heading with the given id.

getItemState
(props: ItemProps) => ItemState

Returns the state of a TOC item