A table of contents with a paper plane that flies to the section you're reading.
Scroll the content and the paper plane flies along the rail between headings, turning where the rail bends. The rail behind it is solid and each heading it passes fills in; the rest stays dashed. Click any heading to scroll to it.
Options you can pass to customize this component.
items*{ id: string; label: string; depth?: number }[]Headings in document order. Each id must match an element id in the content. Depth sets the indent level and defaults to 0.
containerRefReact.RefObject<HTMLElement | null>Scroll container to track and scroll within. Defaults to the window when omitted.
offsetnumberDistance in pixels below the scroller's top edge where a heading counts as reached. Clicking an item scrolls its heading to this line.
indentnumberHorizontal step in pixels for each depth level.
titlestringText above the list. It also names the navigation for screen readers.
classNamestringExtra classes merged onto the root nav. Inner parts carry data-slot attributes (rail-toc-title, -list, -plane) for styling from CSS.
npx shadcn@latest add swamimalode07/rare-ui/rail-toc"use client"import { useRef } from "react"import RailToc, { type RailTocItem } from "@/components/ui/rail-toc"const items: RailTocItem[] = [{ id: "install", label: "Installation" },{ id: "requirements", label: "Prerequisites", depth: 1 },{ id: "usage", label: "Usage" },]export function Docs() {const scrollRef = useRef<HTMLElement>(null)return (<main ref={scrollRef} className="flex h-full gap-12 overflow-auto"><article><h2 id="install">Installation</h2><h3 id="requirements">Prerequisites</h3><h2 id="usage">Usage</h2></article><aside className="sticky top-4 h-max"><RailToc items={items} containerRef={scrollRef} /></aside></main>)}// tracks the window with no container ref// <RailToc items={items} />
Click the code icon in the top-right corner to view the source code.
Most components here are recreations of great work from around the web. I don't claim to be the original creator - this is my attempt to reverse-engineer, replicate, and often add a few extra features. I've tried to credit everyone; if I missed someone, let me know.
1