Rail TOC

A table of contents with a paper plane that flies to the section you're reading.

Dependencies

motion

Interaction Type

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.

Props

Options you can pass to customize this component.

Prop
Type
Description
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.

containerRef
React.RefObject<HTMLElement | null>

Scroll container to track and scroll within. Defaults to the window when omitted.

offset
number

Distance in pixels below the scroller's top edge where a heading counts as reached. Clicking an item scrolls its heading to this line.

indent
number

Horizontal step in pixels for each depth level.

title
string

Text above the list. It also names the navigation for screen readers.

className
string

Extra classes merged onto the root nav. Inner parts carry data-slot attributes (rail-toc-title, -list, -plane) for styling from CSS.

Installation

npx shadcn@latest add swamimalode07/rare-ui/rail-toc

How to use

"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} />

Source Code

Click the code icon in the top-right corner to view the source code.

Keep in mind

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.

Credits

  • •Inspired by pinterest.com/pin/1118863101209303811

Contact

Found a bug or issue? Feel free to drop a DM.

License & Usage

  • •MIT with the Commons Clause and an attribution requirement. Free to use, modify and ship in personal and commercial projects, closed source included. You own the code once it is in your project.
  • •Credit is required. Any project shipping a Rare UI component must credit Rare UI with a visible link back to rareui.com, in a footer, an about page, a credits screen or a README.
  • •Don't strip the credit or the copyright notice from the source you copied.
  • •Don't sell, sublicense or redistribute the components themselves, on their own, bundled into a template, kit, theme or paid course, or ported to another framework.
  • •Don't republish them. No mirrors, no re-uploads, no listing them as your own work.
  • •Don't repackage the registry as a competing component library.
  • •Don't claim authorship of a component or of Rare UI itself.
  • •The LICENSE file in the repository is the full text and governs. Ask first if your use doesn't fit these rules.
Rail TOC