Stat Card
A compact KPI card for dashboards and summary panels: one big featured number, a short uppercase caption underneath, an optional tone-coded delta (↑ / ↓ / →), and an optional icon anchored top-right. Smaller and more number-forward than InsightCard; purely presentational with no motion.
42%
Conversion
+3.2pt vs. last week
Customize
Size
md
Delta
up
Slots
Installation
npx shadcn@latest add https://craftbits.dev/r/stat-card.jsonUsage
import { StatCard } from "@craft-bits/core";
<StatCard value="1,284" label="Active users" />With a tone-coded delta and a leading icon:
import { TrendingUp } from "lucide-react";
<StatCard
value="42%"
label="Conversion"
delta={{ direction: "up", label: "+3.2pt", srSuffix: "vs. last week" }}
icon={<TrendingUp size={16} />}
/>A "regression" tile — same shape, error tone via direction: "down":
<StatCard
value="312ms"
label="Avg. response"
delta={{ direction: "down", label: "-48ms", srSuffix: "vs. last week" }}
/>Anatomy
- Value — the big featured number. Heading face,
tabular-nums. Scales withsize. - Label — short uppercase caption underneath. What the number is.
- Delta — optional
{ direction, label, srSuffix? }row. Arrow glyph + label, tone-coded bydirection. - Icon — optional 4×4 slot anchored absolute top-right. Inherits
currentColorvia the muted text tone.
Delta tones
- up →
cb-success(green) ·↑ - down →
cb-error(red) ·↓ - flat →
cb-fg-subtle(neutral) ·→
The arrow glyph is aria-hidden; pair it with srSuffix (e.g. "vs. last week") so the delta reads as a complete sentence in the screen-reader path.
Sizes
- sm —
text-xlvalue,px-3 py-2outer. Dense dashboard grids. - md (default) —
text-2xl,px-4 py-3. The everyday tile. - lg —
text-3xl,px-5 py-4. Hero-row metrics.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
value | ReactNode | required | The big featured number. Heading face, tabular-nums. |
label | ReactNode | required | Short uppercase caption. |
delta | StatCardDelta | — | { direction, label, srSuffix? } row. |
icon | ReactNode | — | Leading icon, anchored top-right. Inherits currentColor. |
size | 'sm' | 'md' | 'lg' | 'md' | Scales the value typography and outer padding. |
className | string | — | Merged onto the root <div> via cn(). |
The native HTML title attribute is replaced by ReactNode props via Omit<HTMLAttributes<HTMLDivElement>, 'title'>.
Accessibility
- Renders as a plain
<div>— no implicit role. Wrap a dashboard tile in<article>or supplyrole="region" aria-labelledby="…"when the card is a discrete landmark. - The leading icon is
aria-hidden="true"; screen readers read only value · label · delta. - The delta arrow glyph (
↑/↓/→) isaria-hidden— direction is encoded in thedirectionprop and color. Pair withsrSuffix(e.g."vs. last week") so the delta announces as a complete sentence. - Both value and delta render with
tabular-numsso live-updating dashboards don't jitter horizontally. - No motion — safe for
prefers-reduced-motion: reduce.
Credits
- Extracted from:
algoflashcards(src/platform/ui/StatCard.tsx). The original wrapped a genericCardwithbevel-tileTailwind chrome and rendered only a value + label. The library version drops the wrapper dependency, switches to--cb-*semantic tokens, adds tone-codeddelta+ leadingiconslots, and exposessizeas a CVA variant.