Stat Cards
KPI cards with a big value, the delta written as a sentence, and a scrubbable sparkline or progress bar beside it — the row every dashboard opens with.
KPI row
@spectrumui/stat-cards
Revenue
$62.5K
↑ 29% vs 30 days ago
Active users
13.9K
↑ 13% vs 30 days ago
Conversion
3.91%
↑ 14% vs 30 days ago
Churn
2.08%
↓ 21% vs 30 days ago
Login to view codeCreate a free account to access component source code
Login to view codeCreate a free account to access component source code
Login to view codeCreate a free account to access component source code
previous + progress — the budget pair
Spent this week
$487.20
↓ 12% from last week
Remaining weekly budget
$118.80
22% of weekly budget
Login to view codeCreate a free account to access component source code
Login to view codeCreate a free account to access component source code
Login to view codeCreate a free account to access component source code
Manual installation
Prefer to copy by hand? Open the Code tab on any example above and switch to the file you need — every source file is there, not just the demo. Drop them in your project like this:
chart-engine.tsxcomponents/spectrumui/charts/chart-engine.tsxstat-cards.tsxcomponents/spectrumui/charts/stat-cards.tsx
There is nothing to install — this chart draws its own SVG and imports only @/lib/utils.
Usage
import { StatCards } from '@/components/spectrumui/charts/stat-cards';
<StatCards cards={cards} columns={4} />- Set
goodWhen: 'down'on metrics where falling is healthy, like churn — otherwise the delta turns red. - Pass
previousto compare against last period instead of the first point in the series. - A card with
progressrenders a bar instead of a sparkline.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
cards | StatCardData[] | STAT_CARDS | One entry per tile. Each takes a label, a series or value, and optionally previous, progress, format, goodWhen and deltaLabel. |
columns | 1 | 2 | 3 | 4 | 2 | Grid columns at the widest breakpoint. Always one column on mobile. |
status | 'ready' | 'loading' | 'empty' | 'error' | 'ready' | Which state to render. All four reserve the same frame height, so nothing shifts when data lands. |
onRetry | () => void | - | Called by the retry button in the error state. Omit it and no button is shown. |
className | string | - | Merged onto the root element. |