# BigNumber

One number, at the size of a headline.

- Group: Data
- Import: `import { BigNumber } from '@misoto22/folio/charts'`
- Page: https://ui.misoto22.com/components/big-number/
- Related: sparkline, figure-band

## When to reach for it

There is exactly one figure to report. A plot of a single value is a plot whose shape carries nothing, and the reader has to decode an axis to recover a number that could simply have been printed.

## Anatomy

- **Label** (required) — What the number counts, as an eyebrow at --ink-3-aa above it. Nothing binds it to the value programmatically — no aria-labelledby, no role — so document order is the whole association.
- **Value** (required) — The number itself, in the editorial face at --fs-lead with tabular figures. Rendered exactly as handed over: no unit, currency or locale is guessed on its behalf.
- **Delta** — The line under the number, from delta: the change through format — a signed percentage unless replaced — and delta.label at --ink-3-aa saying what it is a change from.
- **Direction mark** — Inside the delta: an aria-hidden arrow, up, down or flat at zero, and the status tint, --ok or --danger, or --ink-2 while nothing has been judged. Two carriers, so the reading survives greyscale and forced colours.
- **Verdict** — The sr-only words beside the arrow — up or down, then better or worse once intent has been set. It is what a screen reader gets in place of the tint.
- **Note slot** — children, under the number with a margin: where a Sparkline, a denominator or a caveat goes.

## Best practices

### Do

- Give the figure something to be judged against. On its own a number cannot be read — 48,210 is neither good nor bad until it is beside last month — and this component carries exactly two places for that: delta for one comparison, children for the Sparkline or the denominator under it.
- Pass delta.value as a ratio. The default formatter multiplies by a hundred and prefixes the sign, so 0.124 prints as +12.4% and 12.4 prints as +1240%. A change already expressed in points needs its own format handed over with it.
- Set intent on any delta meant to be coloured. It defaults to neutral, which renders the change at --ink-2 and says only which way it moved — correct for a figure nobody has judged, and rarely what the author of a revenue card thought they had written.
- Let value be null when there is no reading. It prints an em dash at --ink-3-aa with an sr-only “No data” behind it, which is a number nobody has; a blank line under a label is a broken layout as far as the reader can tell. emptyValue changes what the dash is.

### Don’t

- Do not expect a delta of exactly zero to carry the intent’s verdict. There is no direction for an intent to judge, so the tone, the arrow and the announced words all say “no change” and stop — a zero under up-is-good used to be announced as “no change, worse” while the page showed no judgement at all.
- Do not separate the label from the number. The value is text in a span rather than a labelled element, and the label is a sibling read before it, so a layout that moves the figure into its own column — or reuses one label over two figures — hands a screen reader a bare number with nothing naming it.

## Accessibility

- The delta’s direction is stated by the call site through intent, never inferred from the sign: “errors down 12%” is good news and “revenue down 12%” is not, and no component can tell which it is holding.
- The arrow and the words carry the direction; the status tint is the third signal, never the only one — so the reading survives greyscale, forced colours and colour blindness.
- value is taken already formatted. The component does not guess a unit, a currency or a locale.

## BigNumber

One number, at the size of a headline. The form most dashboards need most often and most chart libraries do not ship, on the grounds that it is not a chart. It is the right answer whenever there is exactly one figure to report: a plot of a single value is a plot whose shape carries nothing, and the reader has to decode an axis to recover a number that could simply have been printed. The delta is where this earns its place over a `<p>`. Direction is stated by the CALL SITE (`intent`), never inferred: "errors down 12%" is good news and "revenue down 12%" is not, and no component can tell which it is holding. Where the direction is known, the arrow and the word carry it — the status colour is the third signal, never the only one.

### Props

- `label` (required) — `ReactNode`. What the number counts.
- `value` (required) — `ReactNode`. The number, already formatted — this component does not guess a unit. `null` and `undefined` are the empty state rather than a blank space: a headline with nothing under it reads as a figure that failed to load, and the reader's next move is to reload a page that will look the same.
- `emptyValue` — `ReactNode` default `'—'`. What stands in for the number when there is none.
- `delta` — `BigNumberDelta`.
- `children` — `ReactNode`. A sparkline, a note, a caveat. Sits under the number.
- `className` — `string`.

## Example — default

```tsx
import { BigNumber } from '@misoto22/folio/charts'

<div className="grid w-full gap-10 sm:grid-cols-3">
  <BigNumber
    label="Monthly revenue"
    value="$48,210"
    delta={{ value: 0.124, label: 'vs last month', intent: 'up-is-good' }}
  />
  <BigNumber
    label="Error rate"
    value="2.4%"
    delta={{ value: 0.08, label: 'vs last week', intent: 'down-is-good' }}
  />
  <BigNumber
    label="Active projects"
    value="1,204"
    delta={{ value: 0, label: 'vs last month', intent: 'neutral' }}
  />
</div>
```

## Example — with sparkline

```tsx
import { Card, CardBody } from '@misoto22/folio'
import { BigNumber, Sparkline } from '@misoto22/folio/charts'

<div className="grid w-full gap-6 sm:grid-cols-2">
  <Card>
    <CardBody>
      <BigNumber
        label="Monthly revenue"
        value="$48,210"
        delta={{ value: 0.124, label: 'vs last month', intent: 'up-is-good' }}
      >
        <Sparkline label="Revenue, last eight months" data={trend} variant="area" />
      </BigNumber>
    </CardBody>
  </Card>

  <Card>
    <CardBody>
      <BigNumber
        label="p95 latency"
        value="1.34s"
        delta={{ value: -0.29, label: 'vs last week', intent: 'down-is-good' }}
      >
        <Sparkline
          label="p95 latency, last eight weeks"
          data={[2.1, 2.0, 1.9, 2.2, 1.8, 1.6, 1.5, 1.34]}
          variant="bars"
        />
      </BigNumber>
    </CardBody>
  </Card>
</div>
```

## Example — points and a missing value

```tsx
import { BigNumber } from '@misoto22/folio/charts'

<div className="grid w-full gap-10 sm:grid-cols-2">
  <BigNumber
    label="Checkout conversion"
    value="4.8%"
    delta={{ value: 0.6, label: 'vs last quarter', intent: 'up-is-good', format: points }}
  />
  <BigNumber label="Refund rate" value="—" />
</div>
```
