Stat Card
KPI card: mono label, icon square, giant value, green/red delta chip with arrow, and an outlined mini bar chart whose last bar is filled. Four solid tones.
brutalist/ui/stat-cardSource
import type { ReactNode } from "react";
import { ArrowDownRight, ArrowUpRight } from "lucide-react";
import { cn } from "@/lib/utils";
export interface StatCardProps {
label: string;
value: string;
/** Change vs previous period, e.g. "+12%". Positive/negative inferred from the sign. */
delta?: string;
deltaLabel?: string;
/** Values for the mini bar chart (any scale). */
series?: number[];
icon?: ReactNode;
tone?: "surface" | "primary" | "accent" | "secondary";
className?: string;
}
const TONES = {
surface: "bg-da-surface text-da-surface-fg",
primary: "bg-da-primary text-da-primary-fg",
accent: "bg-da-accent text-da-accent-fg",
secondary: "bg-da-secondary text-da-secondary-fg",
} as const;
export function StatCard({ label, value, delta, deltaLabel = "vs last month", series, icon, tone = "surface", className }: StatCardProps) {
const negative = delta?.trim().startsWith("-") || delta?.trim().startsWith("−");
const max = series && series.length ? Math.max(...series) : 1;
return (
<div className={cn("da-stroke flex flex-col gap-4 p-5 shadow-da-md", TONES[tone], className)}>
<div className="flex items-center justify-between gap-3">
<p className="font-da-mono text-[11px] font-bold tracking-da-label uppercase">{label}</p>
{icon && (
<span aria-hidden className="da-stroke grid size-8 place-items-center bg-da-bg text-da-fg [&_svg]:size-4">
{icon}
</span>
)}
</div>
<p className="font-da-display text-5xl leading-none tracking-da-display">{value}</p>
{delta && (
<p className="flex items-center gap-2 text-sm font-bold">
<span className={cn("da-stroke inline-flex items-center gap-0.5 px-1.5 py-0.5 font-da-mono text-xs", negative ? "bg-da-danger text-da-danger-fg" : "bg-da-success text-da-success-fg")}>
{negative ? <ArrowDownRight aria-hidden className="size-3.5" strokeWidth={3} /> : <ArrowUpRight aria-hidden className="size-3.5" strokeWidth={3} />}
{delta}
</span>
<span className="opacity-75">{deltaLabel}</span>
</p>
)}
{series && series.length > 0 && (
<div aria-hidden className="flex h-14 items-end gap-1">
{series.map((v, i) => (
<span key={i} className={cn("flex-1 border-[length:var(--da-border-width)] border-current", i === series.length - 1 ? "bg-current" : "bg-transparent")} style={{ height: `${Math.max(8, (v / max) * 100)}%` }} />
))}
</div>
)}
</div>
);
}
export default StatCard;
modules/brutalist/ui/stat-card/index.tsx
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label* | string | — | Metric name. |
| value* | string | — | Formatted value. |
| delta | string | — | Change, e.g. "+12%" or "−9%" (sign drives color). |
| deltaLabel | string | "vs last month" | Comparison period. |
| series | number[] | — | Mini bar chart values. |
| icon | ReactNode | — | Icon in the corner square. |
| tone | "surface" | "primary" | "accent" | "secondary" | "surface" | Card color. |
| className | string | — | Classes on the card. |
Other card variants in Brutalist
Card
Composable card (Card, CardHeader, CardKicker, CardTitle, CardDescription, CardContent, CardFooter) with 5 solid tones, 3 hard-shadow depths and an interactive press-on-hover mode.
Profile Card
User/team member card: striped blue banner with status chip, overlapping yellow initials square, uppercase name and mono role, bio, ruled stat strip and a split action bar.
Release Card
Changelog entry card: yellow version/date column (top bar on mobile), uppercase title (optional link), summary and a list of changes tagged new / improved / fixed / breaking with fixed-width colored labels.
Card in other art directions
Card
Composable frosted card (Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter) with frosted / tinted-gradient / solid variants, specular top edge and interactive lift.
Meeting Card
Meeting recap glass card: title, time / duration / platform meta, gradient participant stack with +N, AI summary panel, action items with checkboxes and owners, and a transcript link.
Profile Card
Teammate glass card: gradient cover, large initials avatar with presence dot, role and timezone, status pill, three stats, expertise tags and Message / Schedule actions.
Stat Ring Card
KPI glass card with a primary→accent gradient progress ring (SVG) showing the percentage, the value over its max and a caption; the ring draws in on mount.
Card
Composable hairline card (Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter) with default / raised / ghost variants and an interactive hover lift.
Incident Card
Incident summary card: severity chip, id and duration, linked title, service chips, a 4-step status progress bar, commander avatar, stacked responder avatars and update count.
Integration Card
Integration tile: logo/monogram, name, category, description, a Radix Switch to enable it, live status meta and a Configure link. Controlled or uncontrolled.
Metric Card
KPI card: muted label, big mono value, inline SVG sparkline with area fill and end dot, and a colored delta chip vs. the previous period (lowerIsBetter flips the colors).
Profile Card
Studio/person profile card in the Read.cv spirit: square gray portrait with initials, name, role and city in mono, availability dot in signal color, short bio and a list of links with ↗.
Project Card
Portfolio project card: neutral image frame that darkens slightly on hover with a “View case ↗” overlay, then a mono meta row (index, client, year) and the title with discipline tags.
Stat Card
Analytics stat: mono label, large display value, change in mono, and a row of thin vertical bars (last bar in ink, others gray) — no chart chrome.
Template Card
Template tile: a wireframe preview drawn with hairlines (nav, giant title, image grid) in a bordered frame, then name, author, category and usage count, with a “Use template” button revealed on hover/focus.
Account Card
Bank account card: institution + masked number header, big balance with available amount, sync timestamp, and three recent inflow/outflow rows.
Invoice Card
Invoice summary card: number + status, bill-to and dates grid, line items table with mono amounts, subtotal/tax/total, and download/send actions.
Kpi Card
Metric card: label, big mono value, colored delta vs. period and an area sparkline in the primary color along the bottom.
Plan Card
Billing/subscription card: current plan + price + renewal date, usage meters (progressbar semantics, turning amber at 80% and red at 95%), manage and upgrade actions.
Action Card
Reduction action card: serif title, description, saving and cost figures, leaf-rated impact/effort, and an “Add to plan” pill that toggles to a sage “In your plan” state.
Article Card
Journal article card: an organic shaped “cover” (arch, blob or circle) with a hand-drawn leaf, category and read time, serif title that underlines on hover, excerpt; whole card is one link.
Metric Card
Emissions metric card: label, big serif value with mono unit, a change chip (down = good, sage; up = clay) and a human equivalence line with a small leaf.
Supplier Card
Supplier card: arch-shaped initials avatar, name, category and country, status pill, share of your footprint and a rounded data-completeness bar with a reminder action.
Profile Card
Rounded teammate card: pastel header band, big emoji avatar in a white circle, name, role, status pill, three stats in soft wells, skill pills and a “Say hi” button.
Project Card
Pastel project card: white emoji tile, name link covering the card, description, chunky rounded progress bar with percentage, tasks-left and due chips, member dots.
Stat Card
Friendly KPI tile: emoji in a white circle, change pill, label, big rounded number and a row of rounded mini bars (last one highlighted); five tones.
Task Card
Kanban task card: round done checkbox with bouncy tick, pastel label, title (struck when done), subtask progress, due chip that turns red when overdue, comment/attachment counts and avatar dots.