Section Rail

Use Section Rail to navigate a long page, case study, or multi-step flow. The active line reflects the section in view and can reveal labels or a context card for nearby sections.

Preview

Reduce motion:Off
Tune:Off
Inspect

Overview

The goal, scope, and main ideas behind this page. A rail answers three questions at a glance: where am I, what is nearby, and where can I go.

Interaction

How the component responds to hover, focus, and scroll. A rail answers three questions at a glance: where am I, what is nearby, and where can I go.

Motion

Direct scroll progress, no bounce, no ambient animation. A rail answers three questions at a glance: where am I, what is nearby, and where can I go.

Accessibility

Labels on focus, aria-current, and reduced-motion support. A rail answers three questions at a glance: where am I, what is nearby, and where can I go.

Installation

Basic usage

TypeScript
article-rail.tsx

Examples

Use scroll mode for heading anchors in a document. Use controlled mode when the active section is managed outside the rail.

Usage

API

PropertyTypeDefaultDescription
itemsSectionRailItem[]requiredThe sections represented by the rail, in document order.
mode"scroll" | "controlled""scroll"`"scroll"` resolves the active item from the page; `"controlled"` leaves it to `activeId` / `onActiveChange`.
activeIdstringundefinedActive item id for controlled usage.
defaultActiveIdstringundefinedInitial active item id for uncontrolled usage.
onActiveChange(id: string) => voidundefinedCalled whenever the active item changes.
showLabels"hidden" | "always" | "active" | "hover""hidden"When labels sit next to the rail on fine pointers. Defaults to `"hidden"` because the context card already names the section, so an inline label would only appear underneath it. Coarse pointers, which never get a card, always show labels.
activeIndicator"dot" | "fill" | "progress""progress"How the active item is marked. `"progress"` fills the active line from the section's own scroll position.
orientation"vertical" | "horizontal""vertical"Direction the rail runs in.
side"left" | "right""right"Which edge the rail is anchored to, which flips label and card placement.
scrollOffsetnumber96Pixels of fixed-header compensation used when scrolling to a section.
getSectionElement(id: string) => HTMLElement | nullundefinedResolves a section element when ids are not real DOM ids.
scrollRootReact.RefObject<HTMLElement | null>undefinedScrolling element the sections live in. Defaults to the page itself.
showPreview"never" | "hover" | "focus" | "hover-and-focus""hover-and-focus"When the context card appears. Cards never appear on coarse pointers.
ariaLabelstring"Section navigation"Accessible name for the rail's landmark.
classNamestringundefinedAdditional classes for the rail root.
lineClassNamestringundefinedAdditional classes for each rail line.
labelClassNamestringundefinedAdditional classes for the item labels.
previewClassNamestringundefinedAdditional classes for the context card surface.

Accessibility

Scroll mode uses real anchor links, while controlled mode uses buttons with the current section exposed to assistive technology. Coarse pointers receive visible labels instead of hover-only targets.

Styling

Use the context-card options for additional editorial detail. Reduced-motion preferences simplify the rail and scroll behavior.

Contact

Found a bug or need help using this component? Open an issue on GitHub.

License & Usage

Sona UI is available under the MIT license. You may use, modify, and distribute this component in personal and commercial projects.

Was this page helpful?

Your response helps us improve component docs.