Stat
A labelled value block — muted label over a value, an honest muted empty state, and an optional delta line. Two scales.
- Status
- Since
0.3.0- Accessibility pattern
- label and value pair
Last updated
Install
Configure registry credentials first using the Quickstart. Before copying this item or any transitive registry dependency, verify the signed manifest and save the exact bytes for Stat before installation. Retain the digest printed by this command.
pnpm exec vegastack-design verify statInstall with the pinned shadcn CLI. Bare shadcn does not verify VegaStack signature or integrity.
pnpm dlx shadcn@4.21.0 add @vegastack/statRun the exact offline --post-write command printed by the preflight, using its saved item path and independently retained --expected-integrity digest. Use the saved preflight for every transitive registry dependency too; stop on any mismatch before using the components.
The same command installs the registry items it composes: @vegastack/skeleton.
Usage
import {
Stat,
StatDelta,
StatEmpty,
StatLabel,
StatValue,
} from "@/components/ui/stat";
<Stat>
<StatLabel>Estimated ARR</StatLabel>
<StatValue>$1M–$10M</StatValue>
</Stat>;Dashboard tiles
size="lg" scales the value to text-2xl (24px, tabular) for stat tiles; add a
StatDelta with intent="up" | "down" | "flat" — the sign/arrow in the copy carries the
meaning, color is never the only signal.
Honest empties
When there is no value, render StatEmpty ("No connection", "No team") in the
text-muted-foreground placeholder register — never a dash or a zero that would read as data. This mirrors the
system-wide inline-empty tier (a muted placeholder span).
Anatomy
Stat is a compound component. Every exported part, with the
data-slot it renders (generated from the canonical source):
Examples
The default scale suits record highlights; the tile preview exercises the large value scale and all three delta intents.
Linked stat tiles
When a count opens the list it counts, make the whole tile the link: an outline Item rendered as
an <a>, with the label first and the value after it. The link's accessible name is the tile's text
in reading order, so each tile announces as "Overdue tasks 3" with no aria-label to keep in sync.
While counts load, a Skeleton stands in for the value and the label keeps naming the link.
Stat group
StatGroup is a compact row of inline stats — "Overdue 1 · Today 3 · Upcoming 12" — in one
hairline-divided strip, for a home page or a dashboard header where four tiles would take a whole
row. It follows its own width, not the viewport: one row of equal cells from 24rem, a 2×2 grid
below. A cell with an href is a link through linkRender (your router's Link), named label
first. undefined is loading (a skeleton holds the value's line), null is a failed read ("—" and
errorLabel, never 0), and hideWhenAllZero renders nothing when every value is exactly zero.
Loading
StatSkeleton is a Stat while it loads — a label bar over a value bar at the Stat's own size —
for a whole band of tiles before any count arrives.
API Reference
Stat
| Prop | Type | Default | Description |
|---|---|---|---|
size | "lg" | "md" | 'md' | Scale — default for facts/highlights rows, lg for dashboard tiles. |
Data attributes and CSS variables on Stat
| Attribute | Values |
|---|---|
data-size | mirrors a prop or state value |
data-slot | "stat" |
StatLabel, StatValue, and StatEmpty
These structural parts accept native <div> props and forward their refs to their respective
elements.
StatDelta
| Prop | Type | Default | Description |
|---|---|---|---|
intent | "down" | "flat" | "up" | 'flat' | Direction of the change — up reads success, down reads destructive,
flat stays muted. Pair the copy with a sign/arrow; color is never the
only signal. |
Data attributes and CSS variables on StatDelta
| Attribute | Values |
|---|---|
data-intent | mirrors a prop or state value |
data-slot | "stat-delta" |
StatSkeleton
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Classes for the block. |
size | "lg" | "md" | "md" | The scale of the Stat it stands in for. |
Data attributes and CSS variables on StatSkeleton
| Attribute | Values |
|---|---|
data-size | mirrors a prop or state value |
data-slot | "stat-skeleton" | "stat-skeleton-label" | "stat-skeleton-value" |
StatGroup
| Prop | Type | Default | Description |
|---|---|---|---|
items* | readonly StatGroupItem[] | — | The stats, in order — usually two to four. |
errorLabel | string | "Couldn't load" | Shown under the dash when a value failed to load. |
formatValue | ((value: number) => string) | (n) => n.toLocaleString() | Formats a value. |
hideWhenAllZero | boolean | false | Render nothing when every value is exactly 0 (loading and failed values are not zero), so
an all-quiet row takes no space. |
linkRender | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | <a /> | The element a linked cell renders as — your router's link (<Link />). The cell's href,
classes and children are merged into it. |
size | "lg" | "md" | "lg" | Scale of each stat's value. |
Data attributes and CSS variables on StatGroup
| Attribute | Values |
|---|---|
data-slot | "stat-group" | "stat-group-grid" | "stat-group-item" |
Each item:
| Prop | Type | Default | Description |
|---|---|---|---|
label* | string | — | The label, read before the value ("Overdue 3"). |
value* | number | null | undefined | — | The count: undefined while it loads, null when the read failed (never shown as 0). |
href | string | — | The list the stat counts — the cell becomes a link through linkRender. |
id | string | — | Stable key; the label is used when omitted. |
Accessibility
- Keep the label visible so the value has an adjacent human-readable name.
- Delta copy carries direction with words or a sign; color is supplementary.
- Use
StatEmptyfor missing data instead of a dash or a misleading numeric zero. - Tabular numerals keep changing values aligned without changing their spoken representation.
- A
StatGroupcell that is loading isaria-busy; its dash on a failed read is hidden from assistive technology, which hearserrorLabelinstead.
| Contract | States tested |
|---|---|
| Behaviour | default, empty, error, success, group, group-link, group-loading, group-failed, group-hidden-all-zero |
| Accessibility | native-or-base-ui-semantics, browser-accessibility-test |
| Visual | default, error, success, empty |