Stat
One headline number with its label, counting up into view, on its own, in a card or in a banner.
Stat shows one number that makes a case: total value, users, yield. It renders a description list, so the label and value stay paired for assistive technology whichever one is on top. Stat has no surface of its own; put it in a Card for the tile.
import { Stat } from '@base-org/bds-web/product/stat';
<Stat value={3} prefix="$" suffix="B+" label="Supplied across Base markets" />;Variants
Default
One number, the value above its label, with no surface. Use it in a hero or
anywhere a box would be one too many. A numeric value counts up as it
scrolls into view; see Number flow.
- Supplied across Base markets
- $3B+
<Stat value={3} prefix="$" suffix="B+" label="Supplied across Base markets" />Featured
The label leads and a display-size value sits at the bottom. Use it for the one number a section is about.
- Average yield
- 4.45%
- Average USD stablecoin yield across Base lending markets, prior to any incentives.
<Stat variant="featured" value={4.45} suffix="%" format={{ minimumFractionDigits: 2 }} label="Average yield" footnote="Average USD stablecoin yield across Base lending markets, prior to any incentives." />Examples
In a card
Wrap a Stat in a Card for a tile, and lay tiles out with Card Group. The Stat fills the card, so in a tall card the value stays at the top and the label at the bottom.
- Average yield
- 4.45%
- Lenders
- 200K+
- Borrowers
- 115K+
<Card.Group columns={2}>
<Card>
<Stat variant="featured" value={4.45} suffix="%" format={{ minimumFractionDigits: 2 }} label="Average yield" />
</Card>
<div className="grid gap-4">
<Card><Stat value={200} suffix="K+" label="Lenders" /></Card>
<Card><Stat value={115} suffix="K+" label="Borrowers" /></Card>
</div>
</Card.Group>Banner
A row of centred stats with no surface, as in base.org's page heroes: two
columns on mobile and one per stat from md, with a wide gap.
align="center" centres each stat and labelStyle="mono" gives the small
uppercase Base Sans Mono label; tiles keep the default sans label.
- Supplied
- $3B+
- Lenders
- 200K+
- Borrowers
- 115K+
<div className="grid grid-cols-2 gap-x-6 gap-y-10 md:grid-cols-3 md:gap-16">
<Stat align="center" tone="neutral" labelStyle="mono" value={3} prefix="$" suffix="B+" label="Supplied" />
<Stat align="center" tone="neutral" labelStyle="mono" value={200} suffix="K+" label="Lenders" />
<Stat align="center" tone="neutral" labelStyle="mono" value={115} suffix="K+" label="Borrowers" />
</div>Number flow
Pass value as a number and Stat counts it up from 0 with
NumberFlow when it is 20% in view, once.
prefix and suffix carry the units, and format takes number format
options such as fraction digits. Under reduced motion, or with
animated={false}, the real figure shows straight away. A string value
renders as is, for a figure that isn't a plain number.
- Builders on Base
- 12,000+
- Settlement
- T+0
<Stat value={12000} suffix="+" label="Builders on Base" />
<Stat value="T+0" label="Settlement" />Tone
brand colours the value brand blue; neutral uses the primary foreground
for pages where blue would compete with the artwork.
- Supplied
- $3B+
- Supplied
- $3B+
<Stat tone="brand" value={3} prefix="$" suffix="B+" label="Supplied" />
<Stat tone="neutral" value={3} prefix="$" suffix="B+" label="Supplied" />Trend and footnote
trend sits beside the value for a short change, such as "+12%". footnote
is small print under the value: a period, a source, a definition.
- Builders on Base
- 12,000++12%
- Last 30 days
<Stat value={12000} suffix="+" label="Builders on Base" trend="+12%" footnote="Last 30 days" />When to use
Use Stat for a headline number: on its own, in a row of two to four cards, or in a banner, on a product surface or a base.org page.
Use something else when:
- The number has a chart or a trend over time. Use Metric Card.
- The tile has a title and body copy rather than a number. Use Card with its own slots.
Usage
Do
Pass the number and its units separately (value={3} prefix="$" suffix="B+") so it can count up. Round to the precision that supports the
claim.
Don't
Animate the number yourself inside value. Stat's count-up already runs
once, respects reduced motion, and settles on the real figure.
- Keep labels to a few words in sentence case; the footnote holds the qualification.
- One
featuredstat per row at most. - For a tile, wrap the Stat in a Card rather than giving it a background or padding yourself, so stats and content cards share one surface. A banner needs no surface.
Props
| Prop | Type | Default |
|---|---|---|
labelrequiredWhat the number measures. | TypeReactNode | Default— |
valuerequiredThe number. A `number` counts up from 0 when the stat scrolls into view; | TypeReactNode | Default— |
align | Type"center" | "start" | null | Defaultstart |
animatedCount a numeric value up from 0 when it scrolls into view. Defaults to | Typeboolean | Defaulttrue |
footnoteSmall print under the value, such as a source, period or definition. | TypeReactNode | Default— |
formatNumber format options for a numeric value, such as fraction digits. | Typeany | Default— |
labelStyle`default` is the sans label of a stat tile. `mono` is the small uppercase | Type"default" | "mono" | null | Defaultdefault |
prefixText before a numeric value, such as "$". | Typestring | Default— |
suffixText after a numeric value, such as "B+" or "%". | Typestring | Default— |
tone | Type"brand" | "neutral" | null | Defaultbrand |
trendA short change indicator beside the value, such as "+12%". | TypeReactNode | Default— |
variant | Type"default" | "featured" | null | Defaultdefault |
Accessibility
Stat renders a dl: the label is the dt, and the value (and footnote) are
dds, so screen readers read "label, value" however the two are arranged.
A numeric value's rolling digits are hidden from assistive technology, and a
visually hidden copy of the final figure (with its prefix and suffix) is read
instead, so screen readers get the real number even before the count-up runs.
trend is part of the value's dd; write it so it reads well after the
number ("+12%", not an arrow alone). Colour carries no meaning on its own: a
brand or neutral tone changes emphasis, not sense.