Prototype Library

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.

Inherited .astro import EsaStat from '@esa/ecology/esa-stat.astro';

Preview

1,284
Active permits
<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.

1,284
Active permits
+12 this quarter
94%
On-time review
rolling 90 days
<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.

14
Monitored sites
3
Needs attention
27
Reports filed
<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.

14
Monitored sites
across 3 counties
1,284
Active permits
+12 this quarter
94%
On-time review
rolling 90 days
3
Needs attention
<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

PropTypeDefaultDescription
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.2M is announced as written. Prefer the full figure, or add an aria-label at the call site.
  • accent is decoration, not meaning — never let the tint be the only signal that a number is the alarming one. Say so in the label or sub.