Skip to content
Textlab
1
Browse

ComponentsNumbers

Stat reveal

A stat counts up when it scrolls in.

12,400+

Installation

$ npx shadcn@latest add @textlab/stat-reveal

Needs @textlab in your components.json. Setup takes a minute.

Usage

usage.tsx
import { StatReveal } from "@/components/textlab/stat-reveal/stat-reveal";

<StatReveal value={12400} suffix="+" />

Variants

countspringscramble

Props

PropTypeDefaultDescription
value*number–The final number.
variant"count" | "spring" | "scramble""count"Ease up, overshoot and settle, or shuffle digits then lock in.
fromnumber0Where the count starts.
prefixstring–Text before the number.
suffixstring–Text after the number.
formatIntl.NumberFormatOptions–Number formatting.
localestring"en-US"Formatting locale.
trigger"mount" | "inView" | "manual""inView"What starts the animation. manual follows `active`.
oncebooleantrueIn view: play once instead of on every entry.
delaynumber0Seconds before the first part moves.
durationnumber1.8Seconds each part takes.
easeEaseName | [number, number, number, number]"emphasized"Easing token or cubic bezier.
asElementType"span"Rendered element.
reducedMotion"user" | "always" | "never""user"user follows the OS setting; always shows the still version.
classNamestring–Merged onto the root.
onComplete() => void–Called when a one-shot animation finishes.

When to use it

Reach for it

  • Stats bands and impact numbers on marketing pages.
  • Any number shown once that deserves a moment of arrival.

Skip it

  • Numbers that keep changing; use rolling-number.
  • Several dozen stats on one screen.

Accessibility and motion

Accessibility

  • Screen readers read the final value, never the in-between numbers.
  • The final width is reserved, so nothing shifts while counting.

Motion

  • Counts with the emphasized ease: fast early, slow landing.
  • Starts when 45% of the stat is visible.
Reduced motion. Shows the final value immediately.

Performance

  • One motion value; text updates outside React renders for count and spring.