Data display
Metric tiles, deltas, sparklines, rank bars, the weekly timeline, and store cards. How numbers appear, and how direction comes before decimals.
#Delta
A delta is the change against the prior week. The sign decides the arrow and the color. It is always a tabular mono figure, and it is always accompanied by its arrow or sign, so color is never the only signal.
Code
<div class="btn-row">
<span class="delta delta-up">↑ 12.4% vs prior</span>
<span class="delta delta-down">↓ 3.1% vs prior</span>
<span class="delta delta-flat">0.0% vs prior</span>
<span class="delta delta-warn">orders open</span>
</div>
<Delta value={12.4} suffix=" vs prior" />
<Delta value={-3.1} suffix=" vs prior" />
<Delta value={0} suffix=" vs prior" />
Use it when
- Comparing this week with the last one
- Next to a headline number or in a timeline row
Don’t use it when
- Comparing across currencies. Never sum or compare money in different currencies
- Showing a raw count with no prior week to compare
#Sparkline
A sparkline is the shape of the last few weeks, oldest to newest, with a dot on the latest. It is teal while the trend holds and turns red when the last point is below the first. It is decorative shape, so it carries an aria-label and the numbers sit beside it.
Code
<div class="btn-row" style="gap: var(--space-8)">
<svg class="spark" viewBox="0 0 88 28" role="img" aria-label="Revenue, recent weeks"><polygon class="spark-area" points="3,28 3,22 23,18 43,20 63,10 85,5 85,28"/><polyline class="spark-line" points="3,22 23,18 43,20 63,10 85,5"/><circle class="spark-dot" cx="85" cy="5" r="3"/></svg>
<svg class="spark spark-down" viewBox="0 0 88 28" role="img" aria-label="Sessions, recent weeks"><polygon class="spark-area" points="3,28 3,6 23,9 43,8 63,17 85,23 85,28"/><polyline class="spark-line" points="3,6 23,9 43,8 63,17 85,23"/><circle class="spark-dot" cx="85" cy="23" r="3"/></svg>
</div>
<Sparkline points={[120, 135, 128, 160, 182]} label="Revenue, recent weeks" />
- Pass at least two points. Fewer than two draws nothing, by design.
- Keep it to about five weeks. Its job is direction, not reading values.
- No axes, no gridlines, no tooltips. If someone needs values, link to the report.
#Metric tile
The unit of the pulse strip: one label, one number, its change, and its recent shape. Nothing else. A fourth line, a hint, is allowed when the number alone would mislead.
Code
<div class="tile">
<div class="label">Revenue</div>
<div class="tile-value num">$18,420</div>
<div class="tile-foot">
<span class="delta delta-up">↑ 12.4% vs prior</span>
<svg class="spark" viewBox="0 0 88 28" role="img" aria-label="Revenue, recent weeks"><polygon class="spark-area" points="3,28 3,22 23,18 43,20 63,10 85,5 85,28"/><polyline class="spark-line" points="3,22 23,18 43,20 63,10 85,5"/><circle class="spark-dot" cx="85" cy="5" r="3"/></svg>
</div>
</div>
<MetricTile
label="Revenue"
value="$18,420"
delta={12.4}
deltaSuffix=" vs prior"
trend={[120, 135, 128, 160, 182]}
trendLabel="Revenue, recent weeks"
/>
Code
<div class="tile">
<div class="label">Low-stock SKUs</div>
<div class="tile-value num">3</div>
<div class="tile-hint">Below reorder threshold</div>
</div>
Use it when
- One number that answers a question: how much, how many
- In a pulse strip of three or four
- Anywhere a change and a shape belong together
Don’t use it when
- A table of many values. Use rank bars or a report panel
- A number with no label
- Mixing currencies in one value
#KPI and rank bars
Inside a report, numbers sit in a panel. A .kpi is a quieter tile on a sunken background. .rank shows top products, channels, or low stock as a name, a value, and a thin bar scaled to the largest value in that list.
# Sales
Code
<section class="panel">
<h3 class="panel-title"><svg class="icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 17l6-6 4 4 8-8M15 7h6v6"/></svg> Sales</h3>
<div class="kpis">
<div class="kpi wide"><div class="value num">$18,420</div><span class="label">Revenue</span><div class="vs"><span class="delta delta-up">↑ 12.4% vs prior</span></div></div>
<div class="kpi"><div class="value num">312</div><span class="label">Orders</span></div>
<div class="kpi"><div class="value num">$59</div><span class="label">AOV</span></div>
</div>
<div>
<div class="label">Top products</div>
<div class="rank">
<div class="rank-row"><div class="rank-head"><span class="rank-name">Linen throw</span><span class="rank-value num">$4,120</span></div><div class="rank-bar"><span style="width:100%"></span></div></div>
<div class="rank-row"><div class="rank-head"><span class="rank-name">Stoneware mug</span><span class="rank-value num">$2,980</span></div><div class="rank-bar"><span style="width:72%"></span></div></div>
<div class="rank-row"><div class="rank-head"><span class="rank-name">Wool socks</span><span class="rank-value num">$1,310</span></div><div class="rank-bar"><span style="width:32%"></span></div></div>
</div>
</div>
</section>
Code
<div class="label with-dot">Low-stock SKUs <span class="alert-dot"></span></div>
<div class="rank">
<div class="rank-row"><div class="rank-head"><span class="rank-name">Stoneware mug</span><span class="rank-value is-warn num">4 left</span></div><div class="rank-bar is-warn"><span style="width:26%"></span></div></div>
<div class="rank-row"><div class="rank-head"><span class="rank-name">Linen throw</span><span class="rank-value is-warn num">9 left</span></div><div class="rank-bar is-warn"><span style="width:60%"></span></div></div>
</div>
- The bar width is data, so it is the one place inline
styleis allowed. - Give a bar a minimum width of about 4% so the smallest item is still visible.
- The bar is a hint of proportion. The number beside it is the value.
#Weekly timeline
A newest-first vertical list, one card per weekly pack. A dashed “Next pack” card sits on top. The latest week gets a filled violet node and a Latest pill. Each card leads with a plain-English headline, then three numbers.
- Next packMondayYour next weekly pack lands Monday.
- Sep 14–20LatestRevenue rose 12% on stronger mug sales.$18,420 revenue ↑ 12.4%312 orders9,840 sessions
- Sep 7–13A quiet week. Orders held steady.$16,390 revenue 0.4%301 orders9,610 sessions
Code
<ol class="timeline">
<li class="tl-item tl-item-next"><div class="tl-card"><div class="tl-head"><span class="tl-week">Next pack</span><span class="pill">Monday</span></div><div class="tl-headline muted">Your next weekly pack lands Monday.</div></div></li>
<li class="tl-item tl-item-latest"><a class="tl-card" href="#timeline"><div class="tl-head"><span class="tl-week">Sep 14–20</span><span class="pill pill-pop">Latest</span></div><div class="tl-headline">Revenue rose 12% on stronger mug sales.</div><div class="tl-metrics"><span><b class="num">$18,420</b> revenue <span class="delta delta-up">↑ 12.4%</span></span><span><b class="num">312</b> orders</span><span><b class="num">9,840</b> sessions</span></div></a></li>
<li class="tl-item"><a class="tl-card" href="#timeline"><div class="tl-head"><span class="tl-week">Sep 7–13</span></div><div class="tl-headline">A quiet week. Orders held steady.</div><div class="tl-metrics"><span><b class="num">$16,390</b> revenue <span class="delta delta-flat">0.4%</span></span><span><b class="num">301</b> orders</span><span><b class="num">9,610</b> sessions</span></div></a></li>
</ol>
Use it when
- The archive of weekly packs, newest first
- Showing “what changed, week by week”
Don’t use it when
- Events that are not weekly packs
- More than about a dozen items without paging
#Store card
The Stores page shows one card per connected store: name, status pill, revenue with its change and sparkline, orders and week, a two-line summary, and a link in. A store with no pack yet shows one calm status line instead of numbers.
Revenue rose 12% on stronger mug sales.
Open store →Code
<div class="store-grid">
<div class="store-card">
<div class="store-card-top"><div class="store-icon">C</div><div class="store-meta"><div class="store-name">Cozy Goods</div></div><span class="pill pill-accent">● Connected</span></div>
<div class="store-trend"><div><div class="label">Revenue</div><div class="num value">$18,420</div><span class="delta delta-up">↑ 12.4% vs prior</span></div>
<svg class="spark" viewBox="0 0 88 28" role="img" aria-label="Revenue, recent weeks"><polygon class="spark-area" points="3,28 3,22 23,18 43,20 63,10 85,5 85,28"/><polyline class="spark-line" points="3,22 23,18 43,20 63,10 85,5"/><circle class="spark-dot" cx="85" cy="5" r="3"/></svg></div>
<div class="store-facts"><span><b class="num">312</b> orders</span><span class="num">Sep 14–20</span></div>
<p class="store-summary">Revenue rose 12% on stronger mug sales.</p>
<a class="btn-link" href="#store-card">Open store →</a>
</div>
<div class="store-card">
<div class="store-card-top"><div class="store-icon waiting">N</div><div class="store-meta"><div class="store-name">North Pier Tea</div></div><span class="pill pill-warn">Waiting for first report</span></div>
<div class="inset"><div class="line">Queued · first pack Monday</div><div class="tile-hint">Expected Sep 28 · covers Sep 21–27</div></div>
<a class="btn-link" href="#store-card">Open store →</a>
</div>
</div>
A store that has no report yet gets a status line and an expected date. No sample values, no skeleton charts.