Description:
SF Interface Numbers is a React component for animated numeric readouts.
When a value changes, it moves only the affected digit columns; the default roll transition passes through intermediate digits.
Preview

Features
- Five transitions:
roll,tick,blur,flip, andscale. - Digit columns that move only when their displayed value changes.
Intl.NumberFormatsupport for currency, percentages, compact notation, and locales.- Prefixes and suffixes that stay next to the changing figure.
- CSS custom properties for timing, digit pitch, fade, blur, and spacing.
- One screen-reader label for the formatted value and a reduced-motion presentation.
How To Use It
Install the package, then import its stylesheet with the component.
npm i @sfinterface/numbersimport { useState } from "react";
import { Numbers } from "@sfinterface/numbers";
import "@sfinterface/numbers/styles.css";
export function QuantityCounter() {
const [quantity, setQuantity] = useState(3);
return (
<div>
<button onClick={() => setQuantity((n) => n - 1)}>−</button>
<Numbers value={quantity} />
<button onClick={() => setQuantity((n) => n + 1)}>+</button>
</div>
);
}Format Prices and Metrics
Pass standard Intl.NumberFormatOptions through format. locale controls separators, currency placement, and numeral systems.
Use prefix or suffix for content outside the formatted number, and avoid a currency prefix when format already supplies the symbol.
<Numbers
value={1125.64}
format={{ style: "currency", currency: "USD" }}
locale="en-US"
/>
<Numbers
value={0.0241}
format={{ style: "percent", maximumFractionDigits: 2 }}
/>
<Numbers value={48200} format={{ notation: "compact" }} />Choose a Transition
roll moves a strip through intervening digits. The other four transitions replace the old glyph with the new one through a slide, blur, flip, or scale effect.
Set trend="up" or trend="down" to force a direction; auto follows the value change.
<Numbers value={count} transition="tick" duration={400} />
<Numbers value={count} transition="flip" />
<Numbers value={count} transition="roll" trend="down" />Available Component Props
| Prop | Type | Default | Purpose |
|---|---|---|---|
value | number | required | Number to display and animate. |
format | Intl.NumberFormatOptions | none | Number, currency, percent, or compact formatting. |
locale | string | string[] | runtime locale | Locale passed to Intl.NumberFormat. |
transition | roll | tick | blur | flip | scale | roll | Digit-change animation. |
trend | auto | up | down | auto | Direction used by moving columns. |
blur | boolean | true | Defocus moving digits. |
fade, softness | number | 1, 0 | Fade reach and shape at the digit-window edges. |
prefix, suffix | ReactNode | none | Content attached before or after the number. |
duration | number | 520 | Transition duration in milliseconds. |
label | string | formatted value | Screen-reader announcement. |
Styling and Accessibility
These CSS tokens control motion and digit geometry:
| Token | Default | Purpose |
|---|---|---|
--sfi-numbers-roll | 520ms | Duration of a digit turn. |
--sfi-numbers-exit | 240ms | Duration for a departing column. |
--sfi-numbers-cell | 1.4em | Vertical pitch between digits. |
--sfi-numbers-blur | 0.09em | Maximum blur on a fast-moving column. |
--sfi-numbers-fade | 1 | Fade reach at the window edge. |
--sfi-numbers-fade-roll | 1.9 | Extra fade reach during a roll. |
--sfi-numbers-softness | 0 | Shape of the fade from crisp to gradual. |
--sfi-numbers-gap | 0em | Gap beside a prefix or suffix. |
--sfi-numbers-ease | cubic-bezier(0.32, 0.72, 0, 1) | Easing for digit movement. |
--sfi-numbers-ease-exit | cubic-bezier(0.4, 0, 1, 1) | Easing for departing columns. |
Override CSS tokens
.metrics {
--sfi-numbers-roll: 700ms;
--sfi-numbers-cell: 1.25em;
--sfi-numbers-gap: 0.25em;
}




