Pro

Stat

A figure with its label and a change stated by both an arrow and words. The hint always takes two lines, so tiles in a row stay level.

October, all events

Open invitations
12
up 3vs last week
Sent and waiting on a reply.
Booked this month
$48,210
up 12%vs September
Confirmed bookings, before refunds.
Average RSVP time
2.4 h
down 18%
From the invitation to the guest’s first reply, across every event, weekdays only.
Clash risk
Low

Installation

With UI Polish connected, ask your agent:

Add the UI Polish stat to this project.

Or with the shadcn CLI:

npx shadcn@latest add https://uipolish.com/r/stat.json
Brings inIcons, Text morph, Text

One figure with its label, an optional change since some earlier point, and an optional hint. Tiles side by side stay level, and when the figure changes, only the digits that differ move.

TSX
<Stat  label="Ticket sales this month"  value={48210}  format={dollars}  delta={{ value: "12%", direction: "up", tone: "positive", label: "vs September" }}  hint="Paid seats, before refunds."/>

When to use it

  • A row of key numbers at the top of a dashboard or report.
  • A single headline figure beside a chart.

When not to

  • More than four or five in a row: past that, nothing stands out. Use a table.
  • Figures without a comparison or context: a lone number rarely means anything. Add a delta or a hint.

Props

PropWhat it does
labelWhat the figure is. One line; too long fades at its end.
valueA number (formatted with format) or a word ("High", "Paused").
formatNumber to text. Defaults to Intl.NumberFormat(locale).
delta{ value, direction, tone?, label? }, see below.
hintOne or two lines of context. Two lines are always reserved.
localeFor the default number format, default "en-US", fixed so the server and browser agree.

delta.direction is "up", "down" or "flat"; it picks the arrow and the words. delta.tone is "positive", "negative" or "neutral"; it picks the color. They're separate because up isn't always good: a reply time going down is good news.

Level tiles

Tiles in a grid share a baseline because every part has a fixed line:

  • The label is always one line (no wrapping).
  • The figure's line box is set by the 32px number face whatever it holds. A word is set smaller (--ui-text-2xl) inside it and sits on the same baseline through the line's strut, so "Low" lines up with "$48,210".
  • The hint always takes two lines, filled or not. Pass hint="" on a tile with nothing to say, to keep its neighbors level. More than two lines fade out at the end of the second.

Nothing ends in an ellipsis: clipped text fades out with a mask, and only when it's clipped.

Direction, not by color alone

The change shows an arrow (drawn by the icon set) and says the direction in visually hidden text, so a screen reader hears "up 12%" and a reader who can't tell green from red still sees the arrow. Flat shows a dash and reads "unchanged". Map --ui-success to your green; the fallback is tuned for both themes.

Motion

WhatDurationEasing
Figure and delta digitstext morph: shared digits stay, changed ones swap, width follows on --ui-dur-move--ui-ease-move
Arrow up ↔ downthe shaft stays, only the head moves (icon set)--ui-ease-move
Arrow ↔ dashstrokes retract and draw--ui-ease-draw
Delta color--ui-dur-instant (120ms)--ui-ease-color

"12" to "11" moves one digit; "$48,210" to "$59,052" keeps the "$", the comma and any digit that stays put. Nothing counts up through the values in between: that's motion with no information in it. Under prefers-reduced-motion: reduce the text swaps.

Accessibility

  • Each tile is a <dl>: the label is the <dt>, the figure, change and hint are <dd>s, so the pairing is announced.
  • Figures are tabular-nums.
  • If a figure changes while the user watches because of something they did, that's fine; if it changes on its own (live data), don't also announce it.

Before / after

Before: a green "+12%" with no arrow, a figure that jumps, tiles that stagger when one hint wraps.

After:

TSX
<Stat label="Average reply time" value="2.4 h" delta={{ value: "18%", direction: "down", tone: "positive" }} hint="Weekdays only." />