StatTile
StableOne big number with how it changed, an optional tiny trend line and an optional limit.
Also known as statistic, stat, kpi, metric
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
A row of shop numbers
Typical wait
28 min
down, -4.1%bettervs previous 7 days
Longest waits
77 min
up, +6.0%worsevs previous 7 days
Time to answer the phone
41 s
down, -2.8%bettervs previous 7 days
Orders
18.4K
up, +9.2%vs previous 7 days
Refunds paid
$1,240
up, +5.1%worsevs previous 7 days
Refund rate
0.8%
down, -0.2 ptsbettervs previous 7 days
Happy customers
92.5%
up, +1.5 ptsbettervs last survey
Likely between 88.1% and 95.4%, from 200 customers
<div className="grid w-full gap-3 sm:grid-cols-2 lg:grid-cols-3">
<StatTile label="Typical wait" value="28 min" goodDirection="down" delta={{ text: "-4.1%", direction: "down", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Typical wait" data={[830, 812, 845, 820, 790, 805, 812]} />} />
<StatTile label="Longest waits" value="77 min" goodDirection="down" delta={{ text: "+6.0%", direction: "up", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Longest waits" data={[2050, 2100, 2200, 2180, 2300, 2250, 2310]} />} />
<StatTile label="Time to answer the phone" value="41 s" goodDirection="down" delta={{ text: "-2.8%", direction: "down", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Time to answer the phone" data={[440, 430, 420, 425, 415, 412, 410]} />} />
<StatTile label="Orders" value="18.4K" goodDirection="neutral" delta={{ text: "+9.2%", direction: "up", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Orders" data={[15.2, 16.1, 15.8, 17.0, 17.6, 18.0, 18.4]} />} />
<StatTile label="Refunds paid" value="$1,240" goodDirection="down" delta={{ text: "+5.1%", direction: "up", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Refunds paid" data={[980, 1020, 1100, 1130, 1180, 1210, 1240]} />} />
<StatTile label="Refund rate" value="0.8%" goodDirection="down" delta={{ text: "-0.2 pts", direction: "down", versus: "vs previous 7 days" }} spark={<Sparkline decorative label="Refund rate" data={[0.6, 0.7, 0.6, 0.9, 1.1, 1.0, 0.8]} />} />
<StatTile label="Happy customers" value="92.5%" goodDirection="up" detail="Likely between 88.1% and 95.4%, from 200 customers" delta={{ text: "+1.5 pts", direction: "up", versus: "vs last survey" }} />
</div>Seven tiles for a shop dashboard. For wait time, sales cost and refunds, lower is better. The happy-customer tile shows its range and sample size.
When to use it
One headline number with how it changed. The change says "better" or "worse" in words, and you choose which direction is good, so a drop in wait time reads as good news.
Made of: Name · Action chip · Big number · Trend line · Change · Detail line · Limit scale
Use it for
- A row of the few numbers that matter most, above the charts.
- A number with its change since the last period.
- A number measured against a limit or target, shown on a small scale.
Not for
- A change over time that people need to read point by point: use LineChart.
- Comparing several amounts: use BarChart.
- How much of an allowance is used or left: use UsageMeter.
Do and avoid
Orders this week
128
up, +9%bettervs last week
128
Do
- Say which direction is good on every tile, so lower-is-better numbers read correctly.
- Say what the change is compared to, such as the previous 7 days.
- For rates from small groups, show the range or group size in the detail line.
- Put one row of tiles above the charts for the numbers that matter most.
Avoid
- Don't use amber for a number that just got worse. Amber means a person must act.
- Don't rely on color for the change. The arrow, the plus or minus and the word "better" or "worse" carry the meaning.
- Don't draw a chart with one bar when a tile says it.
- Don't add labels to the trend line. The tile's number and change say it.
On a phone
- The tile fills the width of its container and the value breaks onto a new line instead of overflowing.
- The sparkline stays at its own size on the right and the text on the left shrinks first.
- Nothing in the tile needs hover or a tap.
Seen in products
- Company blogs about monitoring AI products show dashboards with slowest response times, volume, cost per model and error rate, and treat time to the first word as a key measure.
- They list typical and slowest response times by model with a count of requests, and quality measures such as test pass rate and user feedback.
- Carbon's dashboards guidance prioritizes data by hierarchy.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| labelrequired | string | none | Metric name in sentence case, without a trailing colon. |
| valuerequired | string | none | Formatted value, for example 1.24 s or $4.2K. |
| serif | boolean | none | Sets the value in the display style. |
| delta | StatDelta | none | text (signed, with unit), direction (up, down or flat) and an optional versus period. |
| goodDirection | "up" | "down" | "neutral" | "up" | Which direction of change is an improvement. Use down for latency, cost and error rate. Neutral shows no better or worse word. |
| detail | string | none | Visible line under the value, such as an interval and sample size. |
| spark | ReactNode | none | Slot for a Sparkline. Pass it with decorative set. |
| threshold | StatThreshold | none | value, max, at and label. Draws a thin scale with a tick at the threshold. |
| needsAction | boolean | none | Shows the amber chip and turns the threshold fill amber. Use only when a person has to act. |
| actionText | string | "Needs review" | Text of the amber chip. |
| className | string | none | Extra classes on the tile. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one StatTile switches all of this from its properties panel, across 12 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| Serif | serif | On or off |
| Good direction | goodDirection | UP, Down, Neutral |
| Needs action | needsAction | On or off |
| Label | label | Any text |
| Value | value | Any text |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- better
- When the delta direction matches goodDirection, the change is shown in green with the word better.
- worse
- When the delta direction is the opposite of goodDirection, the change is shown in red with the word worse.
- flat or neutral
- A flat change, or goodDirection set to neutral, is shown in the muted colour with no verdict.
- needs action
- Pass needsAction to add an attention tag and turn the threshold bar to the warning colour.
- threshold
- Pass threshold to show a meter bar with a marker at the limit and its label below.
Tokens
Change one of these and every part that uses it follows.
--success-fg--danger-fg--attention-soft--attention-fg--fg--fg-muted--border--radius-control--radius-card
Built in
- Each tile is a group named by its label.
- Screen readers hear the change as a direction word, such as "up", then the amount and "better" or "worse".
- The arrow is hidden from screen readers. Color only repeats what the words say.
- The limit scale is a meter, read with the value and the limit's label.
What you need to do
- Set goodDirection on every tile where lower is better, or a drop is called "worse".
- Say what the change is compared to in versus, such as "vs previous 7 days".
- Pass a trend line with decorative set, so screen readers do not hear the numbers twice.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide