Chaptered Report Shell
An annual-report / white-paper page shell — a sticky chapter rail generated automatically from the content, giant chapter numbers cross-fading between chapters, full-bleed color-block transitions between sections, and a dual reading-progress indicator.
This is a WebberUI Pro component
Free during the launch campaign: sign up or sign in, then hit “Copy install command” in the preview above and it installs straight away — no payment, no credit card. The command below returns 401 while you are signed out.
npx shadcn@latest add "https://webberui.com/r/chaptered-report-shell.json?t=<install token>"Playground
Tune the props live — the code snippet updates as you go, so you can dial in the look you want before copying it.
<ChapteredReportShell />
Installation
npx shadcn@latest add "https://webberui.com/r/chaptered-report-shell.json?t=<install token>"Usage
Drop ReportChapter children straight in, and the chapter rail on the left is generated automatically from their id / title / number. When a chapter number is not specified, they are numbered in order as two digits:
import {
ChapteredReportShell,
ReportChapter,
} from "@/components/ui/chaptered-report-shell";
<ChapteredReportShell eyebrow="2025 Annual Report">
<ReportChapter id="overview" title="Year in Review" kicker="Overview">
<p>Body copy for chapter one…</p>
</ReportChapter>
<ReportChapter
id="financials"
title="Financial Performance"
kicker="Financials"
accentClassName="bg-indigo-600 dark:bg-indigo-500"
>
<p>Body copy for chapter two…</p>
</ReportChapter>
<ReportChapter
id="outlook"
title="Looking Ahead"
accentClassName="bg-amber-500"
>
<p>Body copy for chapter three…</p>
</ReportChapter>
</ChapteredReportShell>When scrolling happens inside a nested overflow container, pass that container's ref to container (both the progress indicators and the transition animations follow it):
const scrollerRef = React.useRef<HTMLDivElement>(null);
<div ref={scrollerRef} className="h-[400px] overflow-y-auto">
<ChapteredReportShell container={scrollerRef} stickyTop={8}>
{/* ... */}
</ChapteredReportShell>
</div>Props
ChapteredReportShell
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Drop ReportChapter children straight in; the rail is generated from their props |
container | RefObject<HTMLElement> | — | When scrolling happens inside a nested overflow container, pass that container's ref |
eyebrow | ReactNode | — | A small heading above the rail, such as "2025 Annual Report" |
label | string | "Chapter navigation" | accessible label for the rail's <nav> |
stickyTop | number | 16 | Offset of the sticky rail and progress bar from the top (px); can be 0 for nested scrolling |
className | string | — | Appended to the outermost container's className |
ReportChapter
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | — | The chapter anchor id, used by rail clicks and the observer to match chapters |
title | string | — | Chapter title, shown on the rail and the transition color block |
number | string | numbered automatically in order | Chapter number string; numbered automatically as two digits (01, 02, …) when omitted |
kicker | ReactNode | — | A category heading at the top left of the transition color block |
accentClassName | string | neutral dark background | Tailwind class for the transition block's background color; must be a solid color that carries white text, such as "bg-indigo-600" |
children | ReactNode | — | Chapter body copy |
className | string | — | Appended to the chapter <section>'s className |
How it works
- The chapter rail is generated entirely from
ReportChapterprops: there is no separate table of contents to maintain, and adding a chapter makes it appear on the rail automatically - The current chapter is determined by an
IntersectionObserver(with the scroll container asroot) that takes each chapter's visible proportion and picks the highest, so switching never skips - The giant chapter numbers cross-fade between chapters with
AnimatePresence: the old number drifts up and fades out while the new one floats in from below and un-blurs - Each chapter opens with a full-bleed transition color block that wipes in from the left (
scaleX) on entering the viewport, with the number and title floating out afterwards - Dual reading-progress indicators: a top progress bar tied to
scrollYProgress, plus a reading cursor sliding along the rail's track with markers lighting up chapter by chapter - Rail items are real
<button>elements that smooth-scroll to their chapter on click and mark the current position witharia-current="location"; the current chapter is also indicated by font weight and color, not by a colored dot alone - On narrow windows the rail collapses automatically (using
@containerto judge the container width), leaving the content column unaffected - When the user has "reduce motion" enabled at the system level: the color blocks appear directly, numbers switch instantly, progress tracks without spring smoothing, and rail clicks scroll instantly — with the layout and content completely unchanged
Vertical Writing Spread
A Chinese/Japanese vertical writing editorial layout built with CSS writing-mode — vertical columns flow right to left with horizontal pull quotes and images interleaved between them, text reveals character by character from top to bottom on entry, and horizontal scrolling advances the column order.
Tri-Pane Workspace Shell
A nav + list + detail master-detail application shell with built-in collapsing, an overlay mode, and a page-by-page responsive state machine, its transitions choreographed as a spring sequence.