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.json

Usage

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 with size.
  • Label — short uppercase caption underneath. What the number is.
  • Delta — optional { direction, label, srSuffix? } row. Arrow glyph + label, tone-coded by direction.
  • Icon — optional 4×4 slot anchored absolute top-right. Inherits currentColor via the muted text tone.

Delta tones

  • upcb-success (green) ·
  • downcb-error (red) ·
  • flatcb-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

  • smtext-xl value, px-3 py-2 outer. Dense dashboard grids.
  • md (default) — text-2xl, px-4 py-3. The everyday tile.
  • lgtext-3xl, px-5 py-4. Hero-row metrics.

Props

PropTypeDefaultDescription
valueReactNoderequiredThe big featured number. Heading face, tabular-nums.
labelReactNoderequiredShort uppercase caption.
deltaStatCardDelta{ direction, label, srSuffix? } row.
iconReactNodeLeading icon, anchored top-right. Inherits currentColor.
size'sm' | 'md' | 'lg''md'Scales the value typography and outer padding.
classNamestringMerged 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 supply role="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 (//) is aria-hidden — direction is encoded in the direction prop and color. Pair with srSuffix (e.g. "vs. last week") so the delta announces as a complete sentence.
  • Both value and delta render with tabular-nums so 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 generic Card with bevel-tile Tailwind chrome and rendered only a value + label. The library version drops the wrapper dependency, switches to --cb-* semantic tokens, adds tone-coded delta + leading icon slots, and exposes size as a CVA variant.