# FatDigits (/docs/charts/fat-digits)

FatDigits answers "which numbers in this dense column are big, before I read them?" The numeral is always the exact
value; font _weight_ is a second, redundant channel — five (or three) ordinal tiers mapped from your `domain` — so the
large numbers pop preattentively as you scan a column. Weight is never the primary read: it is ordinal and coarse, and
the number is right there.

```tsx
<span
  style={{ display: "inline-flex", flexDirection: "column", alignItems: "flex-end", gap: 2 }}
  className="tabular-nums"
>
  <FatDigits value={1204} domain={[0, 2100]} summary={false} fontSize={16} />
  <FatDigits value={318} domain={[0, 2100]} summary={false} fontSize={16} />
  <FatDigits value={2100} domain={[0, 2100]} summary={false} fontSize={16} />
  <FatDigits value={76} domain={[0, 2100]} summary={false} fontSize={16} />
</span>
```

## Install

```tsx
import { FatDigits } from "@microcharts/react/fat-digits";

<FatDigits value={1204} domain={[0, 2100]} title="Revenue" />
```

Setup (package + stylesheet): [Quickstart](/docs/quickstart#set-up-with-an-ai-agent) or paste [`/agent-setup.md`](/agent-setup.md) into your agent.


## When to use it

- **Good for** — a dense numeric table column you scan for the big ones, a KPI number that should carry its own
  magnitude, or an amount in a sentence.
- **Avoid for** — trends (Sparkline), proportions (Progress), or comparisons (MiniBar).


## Variants

```tsx
<FatDigits value={1902} encode="digit" />
<FatDigits value={1204} domain={[0, 2100]} tiers={3} />
```

`format` also takes `Intl.NumberFormatOptions` — the numeral itself follows the locale's own grouping and decimal marks.

```tsx
<FatDigits
  value={12040}
  domain={[0, 20000]}
  format={{ style: "currency", currency: "EUR", maximumFractionDigits: 0 }}
  locale="de-DE"
/>
```

## Edge cases

```tsx
// without a domain a lone number has no tier to sit in, so it
// renders at the middle weight rather than implying a magnitude it can't know
<FatDigits value={1204} />
```

```tsx
<FatDigits value={Number.NaN} domain={[0, 2100]} />
```

A non-finite value renders nothing (no numeral, no weight) and reports **"No data."** rather than guessing a tier.


## Why this default

Value mode with five tiers is the default because scanning a column is the use case, and five is the most weight steps
that stay discriminable at text size. Always pass a `domain` — without one a lone number has no tier to sit in, so it
renders at the middle weight and means nothing. `encode="digit"` instead weights each digit by its own magnitude, a
redundancy that helps scan long ids and amounts. This is adapted from the FatFonts idea: the research encodes magnitude
as glyph ink area with a custom font; shipping a font would add a dependency, so weight tiers on the inherited font
carry the ordinal instead — the numeral is always the exact value. On a font without many weights the browser snaps to
the nearest available face, so fewer of the tiers stay visually distinct.

## Accessibility

The accessible name is the exact value and its tier — **"1,204 — tier 3 of 5."** — and in digit mode just the number,
since each digit carries its own weight. The interactive entry eases the weight to its new tier on variable fonts (it
snaps otherwise) with no layout shift, and announces the value and tier through a polite live region.

This chart is a single unit, so there is nothing to rove between: a click, tap, `Enter` or `Space` selects it
and fires `onSelect`, and no selection stays pinned. That is the scalar half of the shared
[interaction contract](/docs/accessibility#one-interaction-contract).

## Props

| Prop | Type | Description |
| --- | --- | --- |
| `value` (required) | `number` | The number (always the exact value). |
| `domain` | `readonly [number, number]` | Maps value to a weight tier — always pass one. |
| `encode` | `"value" \| "digit"` | value weights the whole numeral; digit weights each digit by its own magnitude. |
| `tiers` | `3 \| 5` | Weight steps (default 5). |
| `animate` | `boolean` | (interactive) Opt-in entrance motion when the chart mounts client-side — add `import "@microcharts/react/motion"` once. Inert on the server, on hydrated server HTML, and under `prefers-reduced-motion`. |

Plus the shared grammar — `data`, `domain`, `color`, `title`, `summary`, `format` — and the layout props (`width`, `height`, `className`, `style`) that every chart accepts. Interactive entries also share `animate` and `live`, and — wherever a chart has more than one navigable unit — `onActive`, `onSelect`, `selectedIndex` and `defaultSelectedIndex`; and — wherever the chart shows a hover value — `readout`. See [the shared grammar](/docs/quickstart#the-shared-grammar).
