# Metric

One reading, on a plate: a label, a figure, and what qualifies it.

- Group: Data
- Import: `import { Metric } from '@misoto22/folio'`
- Page: https://ui.misoto22.com/components/metric/
- Related: big-number, status-dot, sparkline

## When to reach for it

Four across on a console. BigNumber is the same idea at headline scale for the ONE figure a view is about, and needs the charts entry; this is the tile, and needs nothing.

## Anatomy

- **Plate** (required) — An <article> at --radius with a hairline round it and 12px of padding, or whatever asChild is handed. It has no heading and no landmark: a row of four is a row of readings, not four sections.
- **Label** (required) — label as an eyebrow at --ink-3-aa. Nothing binds it to the figure programmatically, so document order is the whole association.
- **Tone dot** — A StatusDot beside the label when tone is set, un-pulsed and aria-hidden. Decoration by construction, which is why whatever it means has to be in detail as well.
- **Figure** (required) — value in the mono face at --fs-item with tabular figures, printed exactly as handed over — no unit, currency or locale is guessed. Tabular because four tiles in a row are read down the column as much as along it.
- **Detail** — detail under the figure at --ink-2 in the small step. One line: what makes the number a reading rather than a count.
- **Aside** — aside, last, unwrapped and unstyled: a Sparkline, a denominator, a caveat. Unlike BigNumber’s note slot it carries no margin of its own, so a tight tile stays tight.

## Best practices

### Do

- Put whatever the tone means into detail as well. The dot is aria-hidden by construction, so a tile whose only account of a failure is that it is red says nothing at all to a screen reader, and nothing in greyscale.
- Format value at the call site. It is printed exactly as handed over, which is what lets a locale, a currency and a unit be decided once by the application rather than guessed four times by four tiles.
- Give the slotted child no children of its own under asChild. The label and the figure are injected into it, so `<Link href="/jobs" />` is the whole call — a child with content of its own gets that content and the tile both.

### Don’t

- Do not reach for this where there is one figure and a change to report. BigNumber has a delta, a direction stated by the call site and an announced verdict; a tone dot is not any of those, and re-implementing them in aside gets the announcement wrong.
- Do not write a sentence into detail under asChild. The whole tile is inside one link, so the link’s accessible name is every word in it read in order, and a clause added there is a clause read out every time the link is reached.
- Do not put a heading inside one. The plate is an <article> with no name, so a heading in it opens a section a screen reader will list — four tiles then read as four sections of the page rather than as one row of figures.

## Accessibility

- The tone dot is aria-hidden without exception, so colour is never the only carrier — the words in detail are.
- value is taken already formatted. The component does not guess a unit, a currency or a locale.
- Under asChild the tile becomes the caller’s element, so the link or button is the whole plate rather than a target inside it.

## Metric

One reading, on a plate: a label, a figure, and what qualifies it. Distinct from `BigNumber`, which is the same idea at headline scale for the ONE figure a view is about, and which needs the charts entry. This is the tile that appears four across on a console: smaller, monospaced rather than editorial, and carrying two things `BigNumber` has nowhere for — a status tone, and a free slot under the number that is not a delta. Those two are the whole reason it exists; a dashboard whose tiles have to be a `<div>` because the delta does not apply is a dashboard with two tile designs in it. The figure is monospace and tabular by construction, because four of these in a row are read down the column as much as along it, and proportional digits put the same magnitude at two different widths.

### Props

- `label` (required) — `ReactNode`. What the figure counts.
- `value` (required) — `ReactNode`. The figure, already formatted — this does not guess a unit or a locale.
- `detail` — `ReactNode`. One line of context. A figure without it is a number, not a reading.
- `tone` — `StatusTone`. How the reading stands. Drawn as a dot beside the label, and only ever a SECOND carrier: the dot is `aria-hidden`, so whatever the tone means has to be in `detail` as well or it reaches nobody who cannot see it.
- `aside` — `ReactNode`. A sparkline, a denominator, a caveat. Sits under the figure.
- `asChild` — `boolean` default `false`. Render `children` as the tile instead of the `<article>`, keeping these styles — how a linkable tile gets a router's own `Link` without this package importing one. The slotted element must take no children of its own: the label, the figure and everything under them are injected INTO it, which is the point. A whole tile inside one link also means the link's accessible name is every word in it, read in order — "Rows, 63,851, newest yesterday" — so keep `detail` short enough to be heard as part of a link.
- `children` — `ReactNode`. The element the tile becomes under `asChild`. Ignored without it.
- `className` — `string`.

Also accepts: `HTMLAttributes<HTMLElement>`.

## Example — default

```tsx
import { Metric } from '@misoto22/folio'

<div className="grid w-full gap-3 sm:grid-cols-2 lg:grid-cols-4">
  <Metric label="Rows" value="63,851" detail="newest yesterday" tone="success" />
  <Metric label="Sync" value="0" detail="failing since Tuesday" tone="danger" />
  <Metric label="Queue" value="12" detail="3 waiting on approval" tone="warning" />
  <Metric label="Accounts" value="7" detail="all reconciled" />
</div>
```

## Example — a tile that is a link

```tsx
import { Metric } from '@misoto22/folio'

<div className="grid w-full gap-3 sm:grid-cols-2">
  <Metric asChild label="Jobs" value="12" detail="3 waiting">
    <a href="#/jobs" />
  </Metric>
  <Metric asChild label="Approvals" value="4" detail="oldest 2 days">
    <a href="#/approvals" />
  </Metric>
</div>
```
