ComponentsNumbers
Rolling number
Each digit rolls to its new value.
Installation
$ npx shadcn@latest add @textlab/rolling-numberNeeds @textlab in your components.json. Setup takes a minute.
Usage
usage.tsx
import { RollingNumber } from "@/components/textlab/rolling-number/rolling-number";
<RollingNumber value={count} format={{ style: "currency", currency: "USD" }} />Variants
shortestupdownProps
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | number | – | The number to show. |
| variant | "shortest" | "up" | "down" | "shortest" | shortest takes the nearer way round; up and down always roll one way. |
| format | Intl.NumberFormatOptions | – | Formatting, for example currency or compact notation. |
| locale | string | "en-US" | Fixed by default so server and client render the same string. |
| duration | number | 0.6 | Seconds a digit takes to settle. |
| bounce | number | 0.1 | Spring bounce, 0 to 0.5. |
| live | boolean | false | Announce changes politely to screen readers. |
| as | ElementType | "span" | Rendered element. |
| reducedMotion | "user" | "always" | "never" | "user" | user follows the OS setting; always shows the still version. |
| className | string | – | Merged onto the root. |
When to use it
Reach for it
- Counters, balances and scores that change while people watch.
- Dashboards where the change itself is information.
Skip it
- Numbers that never change after load; use stat-reveal.
- Values updating many times a second; the motion becomes noise.
Accessibility and motion
Accessibility
- Screen readers read the formatted value, not the reels.
- Set live to announce updates; leave it off for values that tick constantly.
Motion
- Each reel runs on a spring, so rapid updates interrupt smoothly.
- Columns are keyed from the right; new leading digits slide in and old ones slide out.
Reduced motion. The new value replaces the old one with no rolling.
Performance
- One spring per digit. Reels re-center silently after each roll so the DOM stays fixed size.