Stat
A single-metric block: a big display value, a readable label, and an optional muted caption. Replaces the bespoke .stat / .stat__value / .stat__label cluster every prototype re-implements.
Preview
<Stat value="1,284" label="Active permits" /> With a caption
The sub line is muted meta — a delta, a reporting period, a qualifier. Keep it short enough not to compete with the label.
<Stat value="1,284" label="Active permits" sub="+12 this quarter" />
<Stat value="94%" label="On-time review" sub="rolling 90 days" /> Accent
accent tints the value with --color-content-brand. Use it to
single out one figure in a row — a headline number among supporting ones. A row where
every stat is accented reads as no emphasis at all.
<Stat value="14" label="Monitored sites" />
<Stat value="3" label="Needs attention" accent />
<Stat value="27" label="Reports filed" /> Stat rows
The component is a bare flex column with a transparent background and no padding
of its own — the surface is the caller's job. Lay a row out with a layout primitive or a grid;
wrap it in an esa-card when the group needs
chrome. Deliberately no <esa-stat-group>: spacing between stats belongs to
the page, not to the metric.
<div style="display: grid; grid-template-columns: repeat(4, 1fr); gap: 2rem;">
<Stat value="14" label="Monitored sites" sub="across 3 counties" />
<Stat value="1,284" label="Active permits" sub="+12 this quarter" />
<Stat value="94%" label="On-time review" sub="rolling 90 days" />
<Stat value="3" label="Needs attention" accent />
</div> API
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | number | required | The metric itself — rendered large, in the display face. |
label | string | required | What the value counts. Sentence case, readable body size — not an uppercase overline. |
sub | string | — | Optional muted caption under the label (a delta, a period, a qualifier). |
accent | boolean | false | Tints the value with the brand secondary emphasis. Off by default keeps it primary text. |
Accessibility
- Renders plain
<div>s — no heading semantics. The value is not an<h*>, so a stat row never disturbs the page's heading outline. - The value comes before the label in the DOM, which is also the reading order screen readers announce. Keep the label self-describing ("Active permits", not "Active") so the pair makes sense read aloud.
- Abbreviate carefully:
1.2Mis announced as written. Prefer the full figure, or add anaria-labelat the call site. accentis decoration, not meaning — never let the tint be the only signal that a number is the alarming one. Say so in the label orsub.