# Stat

> A number worth looking at, with what it means and which way it moved.

A stat is a label, a value, and optionally a change. `statGroup()` joins several into one surface with dividers between them.

## Basic stat

```javascript
statGroup(
  stat({ label: 'Pages', value: '204' }),
  stat({ label: 'Build time', value: '1.1s' }),
  stat({ label: 'Client JS', value: '3.3 kB' }),
)
```

## With a change

The change takes its colour from `color` — green for a number that went the right way, red for one that did not. Do not rely on the colour alone: keep the sign or the word.

```javascript
statGroup(
  stat({ label: 'Pages', value: '204', change: '+8 this week', color: 'success' }),
  stat({ label: 'Build time', value: '1.1s', change: '−0.3s', color: 'success' }),
  stat({ label: 'Bundle', value: '9.9 kB', change: '+1.2 kB', color: 'danger' }),
)
```

## With icons

```javascript
statGroup(
  stat({
    label: 'Deploys',
    value: '128',
    color: 'primary',
    icon: icon('zap'),
  }),
  stat({
    label: 'Contributors',
    value: '17',
    color: 'primary',
    icon: icon('user'),
  }),
)
```

## Help text

```javascript
statGroup(
  stat({
    label: 'Lighthouse',
    value: '100',
    change: 'accessibility',
    color: 'success',
    help: 'Measured on every English page in CI.',
  }),
  stat({
    label: 'Pagefind index',
    value: '204',
    help: 'Rebuilt at the end of every build.',
  }),
)
```

## On its own

A single stat needs no group — it just has no surface of its own.

```javascript
card(
  cardBody(stat({ label: 'Total pages', value: '204', change: '+8', color: 'success' })),
)
```

## Fixed columns

Stats auto-fit by default. `columns` pins the count when the numbers should stay on one row.

```javascript
statGroup({ columns: 'repeat(2, 1fr)' },
  stat({ label: 'Passing', value: '215', color: 'success' }),
  stat({ label: 'Failing', value: '0', color: 'success' }),
)
```

## From data

```javascript
return (() => {
  const report = [
    { label: 'Pages', value: 204 },
    { label: 'Assets', value: 208 },
    { label: 'Total', value: '9.7 MB' },
  ]

  return statGroup(
    report.map((entry) => stat({ label: entry.label, value: String(entry.value) })),
  )
})()
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `label` | `Child` | — | What the number counts. |
| `value` | `Child` | — | The number itself, set in tabular figures. |
| `change` | `Child` | — | A delta, coloured by color. |
| `color` | `'primary' \| 'neutral' \| 'success' \| 'warning' \| 'danger'` | — | Colours the change and the icon. |
| `icon` | `Child` | — | Decorative glyph above the label. |
| `help` | `Child` | — | A quieter line under everything else. |

`statGroup()` takes `columns` — any `grid-template-columns` value.
