Data display
Stat
Stat is the KPI tile for dashboards: a label, one big number, the change since the last period and an optional sparkline and footnote. The change is always written out with an arrow and a sign, and you decide whether a rise is good or bad, so a drop in churn or latency can read as good news.
On this page
Monthly revenue
$48,210
Up 12.4% (positive)vs SepActive customers
1,284
Up 3.1% (positive)vs SepChurn rate
1.8%
Down 0.4 pts (positive)vs SepAvg. response time
212 ms
Up 18 ms (negative)vs Sep<StatGroup columns={4}> <Stat variant="plain" label="Monthly revenue" value="$48,210" delta={{ value: "12.4%", direction: "up", label: "vs Sep" }} spark={[29, 31, 30, 34, 36, 35, 38, 40, 39, 42, 43, 48]} sparkLabels={months} format="compact" /> <Stat variant="plain" label="Active customers" value="1,284" delta={{ value: "3.1%", direction: "up", label: "vs Sep" }} spark={[1010, 1032, 1048, 1061, 1090, 1112, 1140, 1171, 1198, 1220, 1245, 1284]} sparkLabels={months} sparkColor={2} /> <Stat variant="plain" label="Churn rate" value="1.8%" delta={{ value: "0.4 pts", direction: "down", intent: "good", label: "vs Sep" }} spark={[3.1, 2.9, 2.8, 2.9, 2.6, 2.5, 2.4, 2.4, 2.2, 2.3, 2.2, 1.8]} sparkLabels={months} sparkColor={3} /> <Stat variant="plain" label="Avg. response time" value="212 ms" delta={{ value: "18 ms", direction: "up", intent: "bad", label: "vs Sep" }} spark={[180, 176, 182, 179, 185, 190, 188, 186, 194, 190, 194, 212]} sparkLabels={months} sparkColor={4} format="ms" /></StatGroup>Usage
import { Stat, StatGroup } from "@/components/ui/stat"; <Stat label="Monthly revenue" value="$48,210" delta={{ value: "12.4%", direction: "up", label: "vs Sep" }} spark={[29, 31, 30, 34, 36, 35, 38, 40, 39, 42, 43, 48]}/>Examples
Overview
Monthly revenue
$48,210
Up 12.4% (positive)vs SepActive customers
1,284
Up 3.1% (positive)vs SepChurn rate
1.8%
Down 0.4 pts (positive)vs SepAvg. response time
212 ms
Up 18 ms (negative)vs Sep<StatGroup columns={4}> <Stat variant="plain" label="Monthly revenue" value="$48,210" delta={{ value: "12.4%", direction: "up", label: "vs Sep" }} spark={[29, 31, 30, 34, 36, 35, 38, 40, 39, 42, 43, 48]} sparkLabels={months} format="compact" /> <Stat variant="plain" label="Active customers" value="1,284" delta={{ value: "3.1%", direction: "up", label: "vs Sep" }} spark={[1010, 1032, 1048, 1061, 1090, 1112, 1140, 1171, 1198, 1220, 1245, 1284]} sparkLabels={months} sparkColor={2} /> <Stat variant="plain" label="Churn rate" value="1.8%" delta={{ value: "0.4 pts", direction: "down", intent: "good", label: "vs Sep" }} spark={[3.1, 2.9, 2.8, 2.9, 2.6, 2.5, 2.4, 2.4, 2.2, 2.3, 2.2, 1.8]} sparkLabels={months} sparkColor={3} /> <Stat variant="plain" label="Avg. response time" value="212 ms" delta={{ value: "18 ms", direction: "up", intent: "bad", label: "vs Sep" }} spark={[180, 176, 182, 179, 185, 190, 188, 186, 194, 190, 194, 212]} sparkLabels={months} sparkColor={4} format="ms" /></StatGroup>With icon and footnote
A footnote says where the number comes from or what period it covers. The delta is optional.
Available balance
$128,940.12
Updated 4 minutes ago from 3 accounts
Outstanding invoices
$21,496
Down $3,210 (positive)since last week12 invoices, 3 overdue
<Stat icon={<Wallet strokeWidth={1.75} />} label="Available balance" value="$128,940.12" footnote="Updated 4 minutes ago from 3 accounts"/><Stat icon={<CreditCard strokeWidth={1.75} />} label="Outstanding invoices" value="$21,496" delta={{ value: "$3,210", direction: "down", intent: "good", label: "since last week" }} footnote="12 invoices, 3 overdue"/>Direction and intent
direction is what the number did; intent is whether that is good. Up defaults to good and down to bad; override it for metrics where lower is better. The arrow and sign carry the direction, color only adds emphasis.
<StatDeltaChip delta={{ value: "12.4%", direction: "up", label: "Revenue, higher is better" }} /><StatDeltaChip delta={{ value: "6.2%", direction: "down", label: "Revenue, a drop is bad" }} /><StatDeltaChip delta={{ value: "38 ms", direction: "down", intent: "good", label: "Latency, lower is better" }} /><StatDeltaChip delta={{ value: "0.9%", direction: "up", intent: "bad", label: "Error rate, a rise is bad" }} /><StatDeltaChip delta={{ value: "0%", direction: "flat", label: "No change" }} />Card grid
On their own, stats render as cards and reflow from one to three columns. Hover the sparkline to read each day.
Seats
9 / 10
Team plan
Uptime, 30 days
99.98%
Up 0.01 pts (positive)vs priorSignups this week
342
Up 8% (positive)<div className="grid gap-4 sm:grid-cols-3"> <Stat icon={<Users strokeWidth={1.75} />} label="Seats" value="9 / 10" footnote="Team plan" /> <Stat icon={<Timer strokeWidth={1.75} />} label="Uptime, 30 days" value="99.98%" delta={{ value: "0.01 pts", direction: "up", label: "vs prior" }} /> <Stat label="Signups this week" value="342" delta={{ value: "8%", direction: "up" }} spark={[38, 41, 44, 52, 47, 56, 64]} sparkLabels={["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]} /></div>Props
Stat
labelrequiredstringdefault: —What the number measures.valuerequiredReactNodedefault: —Pre-formatted value: "$48,210", "99.98%".deltaStatDeltadefault: —Change since the comparison period (see below).iconReactNodedefault: —Small icon before the label.sparknumber[]default: —Trend values for the sparkline.sparkLabelsstring[]default: —One label per value; turns on the sparkline tooltip.sparkColor1 | 2 | 3 | 4default: 1Chart series color.format"number" | "compact" | "percent" | "ms" | "usd"default: —Format of values in the sparkline tooltip.footnoteReactNodedefault: —Source, period or definition.variant"card" | "plain"default: "card"plain drops the frame, for StatGroup or a Card.
StatDelta
valuerequiredstringdefault: —Change without a sign: "12.4%", "$3,210".directionrequired"up" | "down" | "flat"default: —What the number did.intent"good" | "bad" | "neutral"default: up good, down badWhether the change is good news.labelstringdefault: —Comparison: "vs last month".
StatGroup
columns2 | 3 | 4default: 4Columns on large screens; one column on phones, two from small screens up.
Accessibility
- The change is spoken as words ("Up 12.4% (positive)"), and shown with an arrow and a sign, so it never relies on green and red.
- Text stays in text colors; only the small delta chip is tinted.
- The sparkline is decorative: the value and delta carry the meaning. Hover shows a tooltip for sighted mouse users.
- Use a full label ("Avg. response time", not "RT") and put the unit in the value.