Stat

A KPI/metric card for dashboards: a label, a big tabular-nums value, a directional trend chip, and optional icon or sparkline. Compose the named parts into a tile, then drop a row of them above a Data Table.

Total orders
1,429
12.4%
vs last month
Revenue
$84,200
8.1%
vs last month
Avg. order value
$58.92
2.3%
vs last month
Refunds
32
5.0%
vs last month

Installation#

# One-time setup (tokens + lib helpers)npx koalaui-cli@latest init# Add this component (its dependencies come along)npx koalaui-cli@latest add stat

Usage#

Stat is composed from named parts, like Card. The Stat root owns the surface, variant, and density; the parts (StatLabel, StatValue, StatTrend) read it from context.

orders-stat.tsxTSX
import {  Stat,  StatHeader,  StatLabel,  StatValue,  StatTrend,  StatCaption,  StatFooter,  StatIcon,} from "@/components/ui/stat"import { ShoppingBag } from "@phosphor-icons/react"export function OrdersStat() {  return (    <Stat>      <StatHeader>        <StatLabel>Total orders</StatLabel>        <StatIcon className="bg-primary/10 text-primary"><ShoppingBag /></StatIcon>      </StatHeader>      <StatValue>1,429</StatValue>      <StatFooter>        <StatTrend direction="up">12.4%</StatTrend>        <StatCaption>vs last month</StatCaption>      </StatFooter>    </Stat>  )}

Group#

StatGroup fuses a row of tiles into one segmented surface, the way a dashboard bands its headline KPIs together instead of floating them as separate cards. The group owns the single border, radius, and shadow; each nested Stat senses the group and sheds its own chrome to lie flush, with hairline dividers between. Set the widest-breakpoint column count with columns (2 | 3 | 4); it steps down gracefully on narrow screens.

Total orders
1,429
12.4%
Revenue
$84,200
8.1%
Avg. order value
$58.92
2.3%
Refunds
32
5.0%

Anatomy#

A tile reads top-to-bottom: a StatHeader pairs the label with a tinted StatIcon (or an action), the StatValue carries the figure in tabular-nums so it never reflows, and a StatFooter sets the trend beside a muted comparison caption.

Total orders
1,429
12.4%
vs last month

Trend#

StatTrend is a soft chip whose arrow and color come from direction: up reads green, down red, and neutral muted. For metrics where down is the good outcome (refunds, churn, bounce rate), set inverted: the color flips to match the meaning while the arrow keeps pointing the honest way. The chip never wraps or shrinks, so a “+1.1 pts” in a narrow tile stays one chip and the row beside it gives way.

Orders
1,429
12.4%
Avg. order value
$58.92
2.3%
Refunds
32
5.0%
Open tickets
17
0.0%

Sparkline#

StatSparkline is built on Chart in sparkline mode: a soft area fill under a trend line that bleeds to the bottom and side edges of the tile. It paints in currentColor, so set the hue with a text utility (text-success, text-destructive) and it themes across all four palettes for free. Pass tooltip to light up each point on hover with a gliding bubble.

Orders this week
18.2%
1,429
Refunds this week
9.0%
32

Count up#

Pass countUp to StatValue and the figure counts up from zero to its value the first time it scrolls into view, the same trigger the marketing sections use, re-counting each time it scrolls back in. It climbs fast and decelerates onto the final figure, so it reads as a real count-up. It reads the string children ("4,100+", "$4.2M", "4.6×") and preserves the prefix, suffix, and comma/decimal format as it counts, riding the built-in tabular-nums so the row never jitters as the count climbs. It no-ops for number-less content and honors prefers-reduced-motion by showing the final figure immediately.

4,100+
Teams building on Koala
$4.2M
Engineering time saved
4.6×
Faster to ship

Variants#

default sits on a hairline border with a soft shadow; outline drops the shadow for flat, gridded dashboards; elevated trades the border for a lifted shadow when a tile needs to float; plain has no tile at all.

Default
1,429
12.4%
Outline
1,429
12.4%
Elevated
1,429
12.4%
Plain
1,429
12.4%

Without a frame#

Most dashboards lead a chart or a card with one big figure, and that figure is not a tile. variant="plain" drops the ring, the shadow, the fill and the padding, and keeps everything else: the display-face figure, the density’s type ramp, and a tighter rhythm between the parts, since there is no frame left to space them against. Lay it on the sheet beside a chart, or inside a Card, where the card is the frame. Inside a StatGroup the group already owns the frame, so a plain tile keeps the group’s padding.

Net sales
$48,290
+8.1%
Sep 21–27, against the week before
Refunds
Money returned to customers this week.
$2,840
-4.2%
32 orders, 2.1% of sales

Parts on their own#

The parts do not need a Stat around them. StatValue, StatTrend, StatLabel and StatCaption (and the header, footer and icon rows) render anywhere with the plain look at the ambient density, so the headline figure of a chart card is a StatValue, and the trend chip beside a number in a description is a StatTrend, the same chip a tile carries. countUp works there too. Only StatSparkline needs a Stat, because it bleeds to the tile’s edges.

Orders
Placed on the storefront.
1,429
Sep 21–27
Traffic sources
12,480 visits+6.3%against last week

Density#

Density is Koala’s cross-cutting spacing axis (see Density). For Stat it tunes padding, gap, the icon tile, and the value size. compact is the dashboard default; comfortable is roomier. Set it per-tile or for a whole grid with DensityProvider.

Compact
1,429
12.4%
Comfortable
1,429
12.4%

Interactive#

A KPI tile is data, not a control, so it stays inert by default. When the whole tile should drill into a detail view, pass asChild to render it as a link and interactive to add the pointer, hover lift, and focus ring. For a per-tile menu instead, drop a Button into the header.

Total orders
1,429
12.4%
View all orders
Revenue
$84,200
8.1%
vs last month

API reference#

Stat forwards all div props and adds variant (default | outline | elevated | plain), density (compact | comfortable), interactive, and asChild. StatGroup bands a row of tiles into one surface and forwards div props plus variant (default | outline | elevated), columns (2 | 3 | 4), and asChild. The parts StatHeader, StatLabel, StatValue, StatCaption, StatFooter, StatIcon all forward div props; StatValue adds countUp to count a string figure up from zero on scroll. StatTrend adds direction (up | down | neutral) and inverted; StatSparkline takes a data: number[], an optional strokeWidth, and tooltip to enable per-point hover. Every part but StatSparkline also renders outside a Stat, with the plain look at the ambient density. Every part accepts className, merged last.

FAQ#

The `Stat` root owns the surface, variant, and density; nest a `StatHeader` (with `StatLabel` plus an optional `StatIcon`), then `StatValue`, then a `StatFooter` pairing `StatTrend` with `StatCaption`. The parts read the root from context, so you never wire props between them.