Stagger reveal
An editorial entrance where a headline rises line by line, then followers stagger in behind it.
API reference
Components
<StaggerReveal />
The orchestration container. Wraps a StaggerRevealHeadline and its StaggerRevealItem followers, and runs the single-cursor mount entrance over them via useStaggerReveal. Server and no-JS output starts visible. On hydration, the layout effect hides the container before paint while it measures and splits the headline, then reveals it for the entrance. Any setup failure restores visibility.
children
The container content: one StaggerRevealHeadline and any number of StaggerRevealItem followers, in the order they should stagger in.
as?
The element to render. Defaults to "div".
className?
Merged onto the container - this is where the layout utilities live (mx-auto flex flex-col items-start gap-6 px-6, etc).
id?
Forwarded to the container element.
<StaggerRevealHeadline />
The split-target heading the container reveals line by line. Renders plain, readable text (the split runs after mount) with the whole-headline aria-label announce. Exactly one belongs inside a StaggerReveal.
children
The plain headline text to split and reveal. Must be a string - splitText operates on text content, so this cannot be arbitrary JSX.
as?
The element to render. Defaults to "h1".
ariaLabel?
The whole-headline announce for assistive tech, read instead of the per-word spans splitText injects. Defaults to children, so the full line is always announced; the container also restores the original text from it on a reduced-motion re-run.
className?
Merged onto the heading - all colour/size/weight shadcn utilities live here. A splitText-driven heading carries its own display treatment via the preview theme, so no font-*/tracking utility is needed.
id?
Forwarded to the heading (e.g. the aria-labelledby target id).
<StaggerRevealItem />
Tags a follower the container staggers in after the headline. Followers reveal in DOM order, each a beat after the last, on the same running cursor the headline started. Drop as many as the layout needs inside a StaggerReveal.
children
The follower's content (a paragraph of copy, a CTA cluster, a trust line).
as?
The element to render. Defaults to "div".
className?
Merged onto the follower - colour/size/layout shadcn utilities live here.
id?
Forwarded to the follower element.
Hooks
useStaggerReveal
The orchestration as a hook, for a consumer who wants to own the container element rather than use StaggerReveal. Attach the returned ref to a container that holds one StaggerRevealHeadline (the split target) and any number of StaggerRevealItem followers. Its layout effect hides the hydrated container until document.fonts.ready resolves and the headline is split, then runs a single delay cursor through the headline lines and followers. Server output remains visible, and any setup failure reveals the original content. Robust to re-runs: a reduced-motion change resets the headline's textContent to the original string before re-splitting, so previous spans are never double-wrapped.
useStaggerReveal(): StaggerRevealHandleReturns
ref
Attach to the container element. The layout effect temporarily hides it while fonts load and the headline is split; server and no-JS output stays visible so setup failures never remove the content.
Functions
runStaggerPreparation
Runs asynchronous measurement/splitting and always invokes the visible-state fallback. Setup errors are intentionally swallowed because the original, unsplit content is the resilient final state.
runStaggerPreparation(prepare: () => Promise<void>, reveal: () => void): Promise<void>Featured in
See the stagger reveal composed into full sections.
