Statistic
A number with its name on it, and — when there is something to compare it against — how far it has moved.
import { Statistic } from 'neba';
<Statistic label="Monthly recurring revenue" value={48210} prefix="$" previousValue={42800} />;A Box with a fixed arrangement laid on it, exactly as Card is. The slots are props rather than compound sub-components for the reason Card gives: the order never varies, so what a caller wants to decide is what goes in each slot.
The delta is a Chip and not a coloured span, which is the whole reason it looks right next to everything else — the same token the rest of the library uses, at the same step down the control ladder, with the same acrylic on it.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| label | ReactNode | — | The name of the number. Card calls the same slot `title`, but what this names is a *value* — which is the thing the library already spells `label` on every field it has |
| value * | number | string | — | The figure. A number is formatted; a string is printed exactly as given, for the values that are not numbers at all — "3h 42m", "A+" |
| format | Intl.NumberFormatOptions | — | How to write a numeric value — the same prop the progress indicators take. Without it a number is grouped by the reader’s own locale and otherwise left alone |
| prefix | ReactNode | — | Set before the figure — a currency sign |
| unit | ReactNode | — | Set after the figure — %, MB, 명. A second slot rather than one adornment with a side, because a currency symbol leads its number and a unit follows it |
| icon | ReactNode | — | A glyph before the label |
| previousValue | number | — | The figure this one is compared against — last month’s, the target. Passing it is what makes the delta appear |
| delta | 'percent' | 'absolute' | 'both' | 'none' | 'percent' | How the difference is written. Percentage by default, because a report is nearly always asking how much a figure has moved rather than by how many. With a previousValue of 0 there is nothing to divide by, so it falls back to the difference itself |
| betterWhen | 'up' | 'down' | 'up' | Which direction counts as good, and so which way the delta is coloured. `up` for revenue, `down` for churn and error rate and page weight. Not decoration: green-for-larger on a bounce rate says the opposite of what the report means, and says it to exactly the reader who is skimming |
| caption | ReactNode | — | A line under the figure — "vs. last month" |
| alignshared | 'start' | 'center' | 'end' | 'start' | Where the block sits in the card. `center` for a row of tiles that read as one band |
| variantshared | 'solid' | 'outline' | 'text' | 'outline' | Weight of the surface — Box’s own, because a Statistic is a Box with an arrangement on it |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | The figure’s type scale, and the sheet’s padding and radius |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | Semantic colour role. Arbitrary colour values are not accepted |
| densityshared | 'default' | 'compact' | 'default' | Padding only — never the height, never the type scale |
| elevationshared | 0 | 1 | 2 | 3 | 0 | Drop shadow depth. 0 means no shadow at all |
| children | ReactNode | — | Anything below the caption: a sparkline, a ProgressLinear against a target |
Every native <div> attribute passes through, along with every Box prop.
Examples
The comparison
betterWhen is what makes the delta trustworthy. Both cards below went up; only one of them is good news, and the colour has to say which. delta decides whether the change is written as a proportion, as the difference itself, or as both.
The figure and the delta both carry a shape, not only a colour — a rising arrow, a falling one, a dash for a figure that has not moved. A report whose "down" is red and nothing else says nothing at all to a reader who cannot separate red from green.
Anatomy
An icon on the label, a unit on the figure, and anything of your own underneath — a ProgressLinear against a target, a sparkline. align="center" is for a row of tiles that should read as one band.
Formatting
format is passed straight to Intl.NumberFormat, the same prop the progress indicators take. Without it a number is grouped by the reader's own locale and otherwise left alone. A string value is printed exactly as given, for the figures that are not numbers at all.
<Statistic label="Revenue" value={48210} format={{ style: 'currency', currency: 'USD' }} />
<Statistic label="Conversion" value={0.0423} format={{ style: 'percent', maximumFractionDigits: 1 }} />
<Statistic label="Median build" value="3m 12s" />prefix and unit are two slots and not one adornment with a side, because they are typographically different things and always have been: a currency symbol leads its number and a unit follows it, in every locale that has both.
When there is nothing to divide by
A percentage against a previousValue of 0 is not a large number, it is an undefined one — so the ratio is dropped and the absolute difference is written instead. Reporting +∞% because last month was the first month is the kind of thing a dashboard does exactly once before nobody trusts it again.
Coming from Ant Design
| Ant | Neba |
|---|---|
title | label — the name of a value, which is what the library already calls label |
value | The same |
precision={2} | format={{ minimumFractionDigits: 2, maximumFractionDigits: 2 }} |
prefix / suffix | prefix / unit |
valueStyle | Not offered. color, size and variant are the axes |
<Statistic.Countdown /> | Not offered. Pass a formatted string as value and tick it yourself |
| — | previousValue, delta, betterWhen — the comparison, which Ant leaves to you |