A sticky table of contents whose active item follows the page as you scroll, marked by an indicator that slides between entries. Clicking an entry scrolls to its section.
npx shadcn@latest add https://hyperblur.dev/r/site-toc-scrollspy.jsonWorks in any React project set up with the shadcn CLI. The file lands in components/hyperblur/site-toc-scrollspy.tsx.
import { SiteTocScrollspy } from "@/components/hyperblur/site-toc-scrollspy"
<SiteTocScrollspy items={[{ id: "intro", label: "Introduction" }, { id: "usage", label: "Usage" }]} />| Prop | Type | Default | Description |
|---|---|---|---|
| items | { id: string; label: string; level?: 1 | 2 }[] | five sample entries | Entries in order. id must match the id of a section element on the page. level 2 indents the entry. |
| root | RefObject<HTMLElement | null> | HTMLElement | null | null | Scroll container that holds the sections. Leave empty to follow the window. |
| activeId | string | Controlled active entry. Pair with onActiveChange. | |
| defaultActiveId | string | Initially active entry. Defaults to the first. | |
| onActiveChange | (id: string) => void | Called when the active entry changes. | |
| offset | number | 16 | Distance in pixels from the top of the scroll area at which a section counts as reached. |
| title | string | "On this page" | Heading above the list. Also the accessible name of the nav. |
| sticky | boolean | true | Stick to the top of the viewport while the page scrolls. |
| stickyTop | number | 24 | Top offset in pixels used when sticky. |
| accent | string | "#2f7bff" | Color of the sliding indicator. |