Counter
Import
Section titled “Import”import { Counter } from '@delightstack/components';Basic Usage
Section titled “Basic Usage” 0
View code
<Counter value={1234} />Examples
Section titled “Examples”Revenue with Prefix
Section titled “Revenue with Prefix”The prefix is rendered smaller and top-aligned, like a superscript.
$ 0
View code
<Counter value={1234567} prefix="$" />Percentage with Suffix
Section titled “Percentage with Suffix” 0.0 %
View code
<Counter value={87.5} suffix="%" decimals={1} />Custom Formatter
Section titled “Custom Formatter”Override the default Intl.NumberFormat with a custom function for compact display.
<Counter value={1500000} format={(n) => { if (n >= 1000000) return (n / 1000000).toFixed(1) + 'M'; if (n >= 1000) return (n / 1000).toFixed(1) + 'K'; return n.toString(); }}/>Locale-Aware Formatting
Section titled “Locale-Aware Formatting”Number separators adapt to the specified locale.
0,00
View code
<Counter value={1234.56} locale="de-DE" decimals={2} />With Delay and Duration
Section titled “With Delay and Duration” 0
View code
<Counter value={9999} duration={2000} delay={500} />Skeleton Loading
Section titled “Skeleton Loading”value is optional — it may arrive late (e.g. while stats load). With skeleton
set, a number-shaped shimmer pill shows until value is available, and the
count-up starts the moment it arrives.
View code
<Counter skeleton value={loading ? undefined : 12845} />| Prop | Type | Default | Description |
|---|---|---|---|
value | number | - | Target number to display; may arrive late (pair with skeleton) |
duration | number | 1500 | Animation duration in milliseconds |
delay | number | 0 | Delay before animation starts (ms) |
decimals | number | 0 | Number of decimal places |
prefix | string | - | Text before the number (rendered small + top) |
suffix | string | - | Text after the number (rendered small + top) |
format | (n: number) => string | - | Custom formatter (overrides Intl.NumberFormat) |
separator | boolean | true | Use locale thousands separator |
locale | string | - | BCP 47 locale for number formatting |
easing | (t: number) => number | quintOut | Animation easing function |
skeleton | boolean | false | Show a number-shaped shimmer pill until value is available; the count-up starts when it arrives. Pill width is set by --counter-skeleton-width (default 4ch) |
id | string | auto | Element ID |
class | string | '' | Additional CSS classes |
Methods
Section titled “Methods”| Method | Description |
|---|---|
restart() | Reset and replay the count animation from 0 to value. Useful for demos and on-demand replays. |
Events
Section titled “Events”| Event | Detail | Description |
|---|---|---|
oncomplete | - | Fired when the animation finishes |
Accessibility
Section titled “Accessibility”- Element has
aria-live="polite"so screen readers announce value changes role="img"with a computedaria-labelincluding prefix, value, and suffix- The true value is always exposed via
aria-label, so assistive tech reads it regardless of the animated visual value prefers-reduced-motiondisables all animation — the final value is shown immediatelyfont-variant-numeric: tabular-numsprevents layout shift during animation- Animation is triggered by
IntersectionObserver— starts only when the element scrolls into view - On the server (SSR) the counter renders at
0, matching the initial client render so hydration is seamless; it then counts up once visible (with JS disabled it stays at0, but the real value remains inaria-label)