ComponentsData display

Stat

One metric with its change and a mini trend: KPI rows, dashboard tiles, record summaries. Values are formatted with Intl in the current locale; the Delta colour follows the metric's intent (is lower better?) and never carries meaning alone. Server-component compatible, no chart library.

Native <dl> + plain SVG components/stat.tsx, components/sparkline.tsx, lib/data-islands.tsx, lib/value-format.tstheme · material · accent · density · font
Visitors
28,412
Up 12.4% vs previous 30 days
Trending up over the last 9 periods
vs previous 30 days
Published posts
144
Up 6 vs previous 30 days
Trending up over the last 9 periods
vs previous 30 days
Form submissions
312
Up 31.0% vs previous 30 days
Trending up over the last 9 periods
vs previous 30 days
Avg. read time
2m 47s
Down 4.1% vs previous 30 days
Trending down over the last 9 periods
vs previous 30 days

Installation

$ pnpm add @vamos-ui/react

The whole kit as one package — get updates by bumping the version. Add the styles to globals.css: @import "@vamos-ui/react/styles.css";

Usage

import { Stat, StatGroup } from "@vamos-ui/react";

<StatGroup>
  <Stat label="Visitors" value={28412} delta={0.124} trend={[4, 6, 5, 8, 7, 9, 12]} comparison="vs previous 30 days" />
  <Stat label="Avg. response" value={4320} format="duration" delta={-0.18} intent="lower-is-better" />
</StatGroup>

Period selection (7D / 30D / 90D) belongs to the parent card, not to Stat.

No count-up animation: numbers are readable immediately and never re-announce.

Examples

Money (CRM)

format="compact-currency" → $1.2M; decimal strings are formatted exactly; pass { type, currency, options } for anything else.

Won this month
$1.2M
Up 18.2%
Trending up over the last 7 periods
Pipeline value
$3,815,400.00
Down $82,000.00
Average deal
€18,400
Up 5.4%

Lower is better

intent decides the colour: a drop in cancellations or response time is good news. neutral keeps it grey.

Cancellation rate
2.4%
Down 12.0% vs October
Trending down over the last 6 periods
vs October
First response time
1h 12m
Up 9.0% vs October
Trending up over the last 5 periods
vs October
Tickets opened
86
Up 14.0% vs October
Trending up over the last 5 periods
vs October

Progress to goal

target adds a goal bar; it turns success-coloured when reached.

Revenue this month
$12,840
Up 8.0%
Goal $46,80027%
New sign-ups
520
Up 21.0% Goal for November
Goal reached104%
Goal for November

Metrics in one surface (HR / PRM)

StatGroup variant="plain" with plain Stats: hairline dividers, one surface (one blur in glass). href turns a stat into a drill-down link.

Active partners
142
Up 3.5%
On leave today
7
Up 2
Open positions
12
Down 3

Delta

Standalone change indicator for table cells and lists — arrow + sign + colour, spoken as "Up 12.4%".

Up 12.4%Down 4.1%No changeNo dataDown 18.0%Up 20.0%
Up 12.4%Down 4.1%No changeUp $1,250.00Down 6

Loading, no data, error

loading sizes the skeleton to label + value; null shows — and reads "No data"; error takes a retry slot.

Visitors
No data
Conversion rate
No data
Tracking starts tomorrow
Revenue
Couldn’t reach the billing service.

en-US and tr-TR

Intl places the sign and percent: +12.4% vs +%12,4; compact $1.2M vs ₺1,2 Mn; durations 2m 47s vs 2 dk. 47 sn.

Revenue · Gelir
$1.2M
Up 12.4%
Avg. visit · Ort. ziyaret
2m 47s
Down 4.1%
Orders · Sipariş
28,412
Up 3.1%
Revenue · Gelir
₺1,2 Mn
%12,4 arttı
Avg. visit · Ort. ziyaret
2 dk. 47 sn.
%4,1 azaldı
Orders · Sipariş
28.412
%3,1 arttı

API

Stat

PropTypeDefault
label
Metric name (dt).
ReactNode—
value
Numbers are formatted; strings shown as is; null → "—" + No data.
number | string | null—
format
"number" | "integer" | "decimal" | "currency" | "compact" | "compact-currency" | "percent" (ratio) | "duration" (s) | "bytes" | { type, currency, options }.
ValueFormat"number"
delta
Change; with deltaKind="percent" a ratio (0.124 → +12.4%).
number | null—
deltaKind
How the delta is formatted.
"percent" | "number" | "currency""percent"
deltaVariant
Delta look.
"text" | "badge""text"
intent
Which direction is good news (colour of delta and trend).
"higher-is-better" | "lower-is-better" | "neutral""higher-is-better"
comparison
Footer line; a string is appended to the spoken delta.
ReactNode—
trend
Sparkline values, oldest first. Summarised for screen readers.
(number | null)[]—
trendVariant
Sparkline style.
"line" | "area" | "bars""line"
target
Progress-to-goal bar.
{ value: number; label?: ReactNode }—
icon
Small icon before the label.
LucideIcon—
href
Whole stat becomes a link.
string—
loading
Skeleton + aria-busy.
booleanfalse
error / errorAction
Error text in place of the value, plus a retry slot.
ReactNode—
variant
Own surface, a cell in a plain StatGroup, or no chrome.
"card" | "plain" | "inline""card"
size
Value 20 / 28 / 40 px (mono, tabular).
"sm" | "md" | "lg""md"
labels
up, down, flat, noData, trendUp/Down/Flat, goal, goalReached.
Partial<StatLabels>—

Delta

PropTypeDefault
value
The change (percent kind = ratio).
number | null—
kind
Formatting.
"percent" | "number" | "currency""percent"
currency
ISO 4217 for kind="currency" (default: provider currency).
string—
intent
Colour semantics.
StatIntent"higher-is-better"
variant
Plain or soft pill.
"text" | "badge""text"
precision
Max fraction digits.
number—
srLabel / comparison
Override or extend the spoken sentence.
string—

StatGroup

PropTypeDefault
columns
Max columns; container queries drop to 2 and 1.
2 | 3 | 44
variant
Separate cards, or one surface with dividers.
"cards" | "plain""cards"

StatLabel / StatValue / StatDelta / StatTrend / StatFooter / StatTarget

PropTypeDefault
StatValue value / format
Formatted value; or pass children.
number | string | null / ValueFormat—
StatTarget value / target / label
Goal bar.
number / number / ReactNode—
...props
Composition parts (dt / dd) for custom layouts.
HTMLAttributes—