# Table of contents

A React component in [Beamline](https://beamline.io/)'s [Navigation](https://beamline.io/components/navigation) category. Live demo: https://beamline.io/components/table-of-contents

The sections of a long page beside it, with the one being read marked as you scroll: the marker travels down the rail between sections, the rail fills with how far you have read, a click glides to the section and hands it focus; the quiet variant is a column of ticks that opens into names when pointed at, and a narrow room folds it into one “On this page” line.

## Use it for

- Long pages read top to bottom: docs, help articles, changelogs, policies, a long settings page, a report.
- Readers jump to a section and want to know where they are.

## Not for

- The app's main navigation ([sidebar](https://beamline.io/components/sidebar)).
- Panels of one object ([tabs](https://beamline.io/components/tabs)).
- Steps of a flow ([stepper](https://beamline.io/components/stepper)).

## Anatomy

- nav landmark with an optional title (“On this page”)
- rail: a hairline the read part of which fills, and the marker on the current section
- items as links, indented by level, the current one marked with aria-current
- ticks variant: one short tick per section whose length says its level; names open on attention
- folded: one button naming the current section, opening the list

## Variants

- **0**: variant: rail · ticks
- **1**: items, or headings read from the page (`scrollRoot` + `selector`)
- **2**: progress: the rail fills with how far the page is read (default on)

## States

- current section (marker, ink colour, aria-current=location)
- hover
- ticks closed / open
- folded (a narrow room) and opened

## Keyboard

- Tab moves through the links; Enter goes to the section and moves focus to its heading
- Folded: Enter or Space opens the list, Escape closes it

## Motion

The marker travels to the new section with its leading edge first (the shared glide) and the read part of the rail grows with the scroll, drawn only on scroll frames. A click glides the page to the section (instant under reduced motion); the ticks open their names with a short fade and width ease. Nothing runs while the page is still.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `items` | `TocItem[]` | — | { id, label, level? } in page order; read from the page when left out. |
| `scrollRoot` | `RefObject<HTMLElement \| null>` | — | The element that scrolls the content; the window by default. |
| `selector` | `string` | — | Headings to read when items are left out. Default "h2[id], h3[id]". |
| `value / defaultValue / onValueChange` | `string \| null` | — | The current section's id; follows the scroll unless controlled. |
| `offset` | `number` | — | Pixels a sticky header covers at the top. Default 0. |
| `variant` | `"rail" \| "ticks"` | — | Default rail. |
| `progress` | `boolean` | — | Fill the rail with how far the page is read. Default true. |
| `title` | `ReactNode` | — | Default "On this page"; null for none. |
| `className / classNames / style / ref` | `string / TableOfContentsClassNames / CSSProperties / Ref<HTMLElement>` | — | The nav and its parts (title, list, item, link, marker, rail). |

## Dependencies

`lucide-react`

## Import

```tsx
import { TableOfContents } from "@/components/table-of-contents/table-of-contents";
```

## Get it

Table of contents is part of Beamline: 200+ components and 50+ complete screens for React that your coding agent (Claude Code, Codex, Cursor or any MCP client) installs into your app through Beamline's MCP server, as a ready-built package or as plain React source you can change. $49 launch price, one payment, no subscription, lifetime updates, one licence for your whole team. [Get Beamline](https://beamline.io/checkout?pack=complete) · [Connect your agent](https://beamline.io/connect)

## More in Navigation

- [Sidebar](https://beamline.io/components/sidebar): The app's main navigation: sections, items with counts and one level of sub-pages, an icon rail with tooltips (⌘B, the trigger or the edge), and a sheet…
- [Tree view](https://beamline.io/components/tree-view): Nested folders and records with the full tree keyboard model (arrows, Home/End, *, type to jump), depth guides, counts and animated opening.
- [Stepper](https://beamline.io/components/stepper): Where someone is in a multi-step flow: done steps carry a check, the current one a ring, and the line between marks fills as steps complete.
- [Tabs](https://beamline.io/components/tabs): Switches between panels of one object; one indicator slides to the active tab, counts sit beside labels, and the tabs a row has no room for fold into More.
- [Navigation menu](https://beamline.io/components/navigation-menu): A site or docs header whose sections open into one panel that resizes and slides between them; NavigationMenuCard is the standard link row.
- [Menu bar](https://beamline.io/components/menubar): A desktop-style File / Edit / View bar for editor-like apps; each menu takes the same rows as the dropdown menu, and pointing moves between open menus.
- [Pagination](https://beamline.io/components/pagination): Moves through pages of a known length: first, last and the current page's neighbours, with an optional “41–60 of 468”. It answers to its own room…
- [User menu](https://beamline.io/components/user-menu): The account menu behind the avatar: who is signed in, status, theme, account pages and sign out with progress; a bottom sheet on phones.
- [Breadcrumb](https://beamline.io/components/breadcrumb): Where a page sits and the way back up; it shows as many levels as its room holds and folds the ones nearest the top into a menu.
