StatCard
KPI number card. Located at apps/web/components/ui/stat-card.tsx.
Usage
<StatCard
label="Total users"
value={42}
hint="+3 this week"
tone="info"
/>
Props
interface StatCardProps {
label: string;
value: string | number;
hint?: string;
tone?: "neutral" | "info" | "success" | "error" | "warning";
icon?: ReactNode;
}
Variants (tones)
Tone mapping follows the same palette as Badge tones:
| Tone | Border | Background tint |
|---|---|---|
| neutral | border-line | none |
| info | border-accent/30 | bg-accent/5 |
| success | border-success/30 | bg-success/5 |
| warning | border-amber-400/40 | bg-amber-50 |
| error | border-error/30 | bg-error/5 |
Layout
┌────────────────────┐
│ LABEL │ <- text-xs, uppercase, muted
│ │
│ 42 │ <- text-2xl, semibold, primary
│ │
│ +3 this week │ <- text-xs, muted
└────────────────────┘
p-4 · border · rounded-[var(--radius)]
Fixed proportions — use in grids like grid-cols-4 gap-3 for dashboard KPI rows.
Common pattern
Admin overview page:
<div className="grid grid-cols-4 gap-3">
<StatCard label="Users" value={totalUsers} hint={`${activeUsers} active`} tone="info" />
<StatCard label="Projects" value={totalProjects} tone="neutral" />
<StatCard label="Docs indexed" value={totalDocs} hint={`${pendingDocs} pending`} tone="success" />
<StatCard label="Share requests" value={pendingShares} tone={pendingShares > 0 ? "warning" : "neutral"} />
</div>
With icon
<StatCard
icon={<IconUsers />}
label="Active users"
value={12}
tone="success"
/>
Icon renders in the top-right of the card, subtle.
Don't
- Don't hand-roll
<div class="text-2xl"><div class="text-xs uppercase text-muted">Label</div></div>. AGENTS.md rule: use StatCard. - Don't use a StatCard for non-numeric data. If value is text ("Active", "Running"), use a row with Badge instead.
- Don't stack StatCards vertically in a wide layout. Use a grid so they sit as a horizontal row of KPIs.