# Number roll (goodtabs UI)

Digits roll like an odometer to a value, each one a column moved by transform.

## Install

```bash
npx shadcn@latest add https://ui.goodtabs.co/r/number-roll.json
```

Or, with the @goodtabs namespace configured in components.json: `npx shadcn@latest add @goodtabs/number-roll`

## Usage

```tsx
import { NumberRoll } from "@/components/ui/number-roll"

<NumberRoll value={48210} className="text-7xl font-medium tracking-tight" />
<NumberRoll value={0.84} decimals={2} suffix="s" />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| value | `number` |  | The number to land on, required. Changing it rolls from the old value. |
| prefix | `string` | `""` | Text before the digits, such as a currency sign. |
| suffix | `string` | `""` | Text after the digits, such as a unit. |
| decimals | `number` | `0` | Digits after the decimal point. |
| locale | `string` | `"en-US"` | Locale for separators. Keep it fixed so the server and the browser agree. |
| duration | `number` | `1.6` | Seconds the entrance takes. A value change takes 0.6 of it. |

## When to use

- Headline stats on a landing page
- A price that changes with a toggle
- A counter that updates every few seconds

## When not to use

- Values in a table people scan: use plain tabular figures
- Numbers that change many times a second
- Long runs of stats, because one or a few rolls say enough

## Notes for agents

- GSAP installs from npm under GSAP's own licence. No GSAP code ships in this registry
- The server renders each column on its final digit, so the value is right with no script. The entrance spins whole turns and lands where it began, so it never shows a wrong number first
- The screen reader string is the formatted value, the columns are aria-hidden. It is not a live region, add one around it if a change must be announced
- A change that adds a digit adds a column at once, because width is not animated. Keep digit counts stable where you can
- Columns clip at 1lh, so leading-none works and tall line heights do too. Use tabular digits from the font, which the component turns on

## The maths

- Position is p mod 10 and one step is 100 / 11 percent of the strip, because the strip has 11 cells with a second 0 to wrap onto.
- Place k moves floor(to / 10^k) - floor(from / 10^k) steps, kept mod 10 plus up to max(0, 2 - k) whole turns, so 0 to 12,480 is 20, 18, 4, 2 and 1 steps from the right.
- Stagger is min(50ms, 300ms / n), 50ms for six digits or fewer.

Docs: https://ui.goodtabs.co/components/number-roll