Stat tiles
tier 2 — classes
One number that matters, with what it is and which way it moved.
.stat-row lays a set of them out without a breakpoint.
A row of tiles
The value is tabular-nums: digits of differing widths make a polling
dashboard reflow every time it updates, and a page that never sits still is a page nobody
can read.
--good and --bad are judgement, not direction. More resolved is
up and good; more open is up and bad. Put a Remix Icon arrow inside to carry the
direction, so it survives the colour-blind palette, a greyscale print and forced
colours.
<div class="stat-row">
<div class="stat">
<span class="stat-label">Open orders</span>
<span class="stat-value">77</span>
<span class="stat-delta stat-delta--bad"><i class="ri-arrow-up-line"></i> 12 since 08:00</span>
</div>
<div class="stat">
<span class="stat-label">Resolved today</span>
<span class="stat-value">143</span>
<span class="stat-delta stat-delta--good"><i class="ri-arrow-up-line"></i> 18%</span>
</div>
<div class="stat">
<span class="stat-label">First response</span>
<span class="stat-value">4:12 <span class="stat-unit">median</span></span>
<span class="stat-delta stat-delta--warn"><i class="ri-arrow-up-line"></i> 0:38</span>
</div>
<div class="stat">
<span class="stat-label">Reservations accepted</span>
<span class="stat-value">86<span class="stat-unit">%</span></span>
<span class="stat-note">of 214 offered</span>
</div>
</div>
Target, link and unavailable
.stat-target is the line saying what the number is measured against. A number on
its own is rarely interesting, and a bar under it is a
.progress — a stat against a target IS progress
towards it, so there is no second track class to drift from the first.
a.stat makes the whole tile a link to the thing it counts.
.stat--unavailable is for a figure that could not be read: an em dash, never a
zero. A dashboard that shows 0 because an endpoint did not answer is a dashboard that lies.
<div class="dr-col dr-gap-3" style="max-width:560px">
<div class="stat-row stat-row--divided">
<span class="stat">
<span class="stat-label">Dispatched</span>
<span class="stat-value">248</span>
<span class="stat-target">of a 300 target</span>
</span>
<a class="stat" href="#stat-variants">
<span class="stat-label">Backordered</span>
<span class="stat-value">12</span>
<span class="stat-delta stat-delta--bad"><i class="ri-arrow-up-line"></i> 4 today</span>
</a>
<span class="stat stat--unavailable">
<span class="stat-label">Warehouse load</span>
<span class="stat-value">—</span>
<span class="stat-target">of a 300 target</span>
</span>
</div>
<div class="stat">
<span class="stat-label">Fulfilment rate</span>
<span class="stat-value">62<span class="stat-unit">%</span></span>
<span class="stat-target">62 of 80 lines reserved</span>
<span class="progress" style="margin-top:6px"><span class="progress-bar" style="width:62%"></span></span>
</div>
</div>
Inside a card
A .stat-row directly inside a .card-body drops the gap and gets
a dividing rule between tiles instead, so the card reads as one object rather than four
floating numbers.
<div class="card" style="max-width:520px">
<div class="card-head"><strong>Last 24 hours</strong></div>
<div class="card-body">
<div class="stat-row">
<div class="stat">
<span class="stat-label">Received</span>
<span class="stat-value">312</span>
</div>
<div class="stat">
<span class="stat-label">Auto-handled</span>
<span class="stat-value">268</span>
</div>
<div class="stat">
<span class="stat-label">Escalated</span>
<span class="stat-value">44</span>
</div>
</div>
</div>
</div>
Which way it moved
--good, --bad, --warn and the bare
.stat-delta. The modifier is judgement, not direction: more open orders
is up and bad, faster dispatch is down and good. Choose it by whether the reader should be
pleased.
The arrow carries the direction, so put a ri-arrow-up-line or
ri-arrow-down-line inside every delta. Colour alone does not survive a
colour-blind palette, a greyscale print or forced colours.
<div class="stat-row" style="max-width:640px">
<div class="stat">
<span class="stat-label">Dispatched</span>
<span class="stat-value">1,204</span>
<span class="stat-delta stat-delta--good"><i class="ri-arrow-up-line"></i> 8% on last week</span>
</div>
<div class="stat">
<span class="stat-label">Open orders</span>
<span class="stat-value">77</span>
<span class="stat-delta stat-delta--bad"><i class="ri-arrow-up-line"></i> 12 since 08:00</span>
</div>
<div class="stat">
<span class="stat-label">Time to dispatch</span>
<span class="stat-value">4.2<span class="stat-unit">h</span></span>
<span class="stat-delta stat-delta--good"><i class="ri-arrow-down-line"></i> 20 min faster</span>
</div>
<div class="stat">
<span class="stat-label">Returns</span>
<span class="stat-value">9</span>
<span class="stat-delta stat-delta--warn"><i class="ri-arrow-up-line"></i> 2 — watching</span>
</div>
<div class="stat">
<span class="stat-label">Regions live</span>
<span class="stat-value">3</span>
<span class="stat-delta"><i class="ri-subtract-line"></i> unchanged</span>
</div>
</div>