Stat Card
The “big number, and which way it's going” tile a dashboard overview is built from — label, value, an optional signed delta, and an optional sparkline.
Usage#
import { StatCard } from "neelam-ui";
<StatCard
label="Active users"
value="12.9K"
delta={0.124}
deltaLabel="vs. previous 30 days"
trend={[180, 190, 210, 240, 290, 340]}
/>value is pre-formatted by you — 12.9K, $4.2M, 3.4 hrs. delta is a
signed ratio, so 0.124 renders as +12.4%; override the rendering with
formatDelta.
It wraps Card rather than restyling a bare div, so
a KPI row and the cards around it share one surface, border, and shadow.
Up is not always good#
deltaDirection decides the delta's colour, because a rise is not universally
good news:
"up-is-good"(the default) — active users, revenue."down-is-good"— response time, error rate, churn."neutral"— no judgement, rendered muted.
Hard-coding green-for-up colours half a dashboard wrong
A 6% rise in average response time is bad news shown in green if you leave the
default in place. Set deltaDirection on every metric where falling is the
win — the demo above does exactly this for response time.
The delta never relies on colour alone#
An arrow icon carries the direction visually, and an sr-only
"increased"/"decreased" carries it to assistive tech. The green or red is
reinforcement, not the signal (WCAG 1.4.1).
Trend#
trend renders a Sparkline under the value. Ten
to fifteen points reads best; the sparkline is decorative, since the number it
trends is already stated right above it.
Typography#
The value uses the font's default proportional figures, deliberately not
tabular-nums: tabular figures give every digit a zero's width, which reads
loose at display sizes. Tabular figures belong in
Table's columns, where digits must line up between
rows.
Loading#
StatCard is presentation only — no fetching, polling, or loading state. Show
one before its data arrives by composing a
Skeleton into the value slot:
<StatCard label="Active users" value={<Skeleton className="h-8 w-20" />} />Keyboard#
| Key | Behaviour |
|---|---|
| Tab | Not focusable. A stat card is a readout — wrap it in a link yourself if it should drill through. |
Accessibility#
- The delta's direction is available three ways: the arrow's shape, the
sr-only"increased"/"decreased" text, and the sign in the formatted percentage. Colour is the fourth, not the first. iconis decorative and hidden from assistive tech — it always duplicates the label beside it.- The sparkline is
aria-hidden, since the headline value states the same thing in words. deltaLabelnames the comparison period. A delta without one is a number the reader cannot interpret — always say what it is measured against.
API reference#
| Prop | Type | Default |
|---|---|---|
labelrequiredWhat the number measures, in sentence case and without a trailing colon. | ReactNode | — |
valuerequiredThe headline number, pre-formatted by the caller (`12.9K`, `$4.2M`, `3.4 hrs`). | ReactNode | — |
deltaSigned change over the comparison period, as a ratio — `0.124` is a 12.4% rise. | number | — |
deltaDirectionWhich way is good news, deciding the delta's color. Defaults to `"up-is-good"`. | enum | up-is-good |
deltaLabelNames the period the delta is measured against, e.g. `"vs. previous 30 days"`. | ReactNode | — |
formatDeltaOverrides the default signed-percentage rendering of `delta`. | ((delta: number) => string) | — |
iconA leading icon for the metric. Decorative — it's hidden from assistive tech. | ReactNode | — |
trendA short series rendered as a `Sparkline` under the value. Ten to fifteen points reads best. | number[] | — |
Also accepts every native <div> attribute except title, which is replaced by
label.