MetricCard
One metric on a card: its title, value and change against the previous period, a small chart of both periods, and when it was updated.
import { MetricCard } from "@butteryui/react";Demo
When to use it
Use it for
- An overview page's headline numbers: sales, new subscribers, refund rate
- A number whose trend matters as much as its value
Not for
- A number with no history: use StatStrip or plain Text
- Many numbers in rows: use DataTable, with a Sparkline per row
Examples
Headline metric
The number a page leads with at size lg on the tint, beside a metric with an outline.
Bags shipped
1,284
vs previous period
Updated 2 min ago
Late shipments
6
vs previous period
Updated 2 min ago
Metric by period
A card whose value, change and chart come from state, picked here by the period above it.
Sales
$12,405.00
vs the week before
Updated 4 min ago
Metric that loads
A metric whose numbers arrive after a moment: its skeleton holds every part in place until then.
Overview metrics
An overview's headline numbers for the week, side by side from the md breakpoint, refreshed together.
Sales metric
One metric: its title and what it means, the value and its change, both weeks charted, and a link to its details.
Variants and states
Overview metrics
Point at a chart to compare the two periods; a refund rate that falls is good news.
Loading
Each part is a skeleton in its own place, and the chart shows its pill after 300ms.
Variants
Beside elevated above: outline, a 1px edge drawn inside; soft, the bg-control fill; tinted, bg-tint from the palettes.
Plain
No surface or padding, for metrics in a row on a page or a panel that's already a surface.
Props
MetricCard
| Prop | Type | Default | Description |
|---|---|---|---|
titlerequired | string | What it measures, such as "Sales". It names the card and its chart. | |
titleAs | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "p" | "h3" | The title's element. Defaults to "h3", under an AppPage.Section's h2. |
info | string | What the metric means, behind an InfoButton after the title: a tooltip on hover and focus, a popover on a press or a tap. | |
value | string | The value, written out, such as "$12,480.00". Leave it out while loading. | |
delta | number | The change against the previous period as a fraction: 0.124 for +12.4%. | |
deltaLabel | string | "vs previous period" | What the change is measured against. Defaults to "vs previous period". |
compared | boolean | Whether the card compares with an earlier period, so its change line keeps its place while loading
and shows "—" when there's no change to work out. Defaults to whether series has a comparison series. | |
lowerIsBetter | boolean | false | Shows a fall as good news (success) and a rise as bad. Defaults to false. |
labels | readonly string[] | The chart's labels, such as the period's days. With series, the card shows a small LineChart. | |
series | readonly ChartSeries[] | The chart's series: the period, and the previous period with comparison: true. | |
formatValue | ((value: number) => string) | Writes a value in the chart's tooltip. Defaults to the number. | |
formatTick | ((value: number) => string) | Writes a gridline's value in the chart. Defaults to a short form, such as 1.2K. | |
updated | string | When the numbers were last updated, such as "Updated 4 min ago". | |
href | string | The metric's details page: the footer's link and the expand button go there. | |
detailsLabel | string | "Details" | What the footer's link says. Defaults to "Details". |
onNavigate | ((href: string, event: MouseEvent<HTMLAnchorElement>) => void) | Runs as either link is followed, where a router can take over. | |
loading | boolean | Shows the card's skeleton: the same parts in the same places, and the chart's loading pill. | |
variant | "elevated" | "outline" | "soft" | "plain" | "tinted" | "elevated" | How it draws its surface: "elevated" (the default), the surface with the card shadow; "outline", a 1px
edge on the surface; "soft", the bg-control fill; "plain", no surface or padding, for metrics laid out
on a page or a panel of their own; or "tinted", bg-tint, a soft fill from the palettes its words and
chart keep their contrast on. |
size | "md" | "lg" | "md" | "md" (the default), the value in title-lg, or "lg", a 32px value for a headline metric. |
It also takes Omit<ComponentPropsWithRef<"div">, "title">.
ChartSeries
One series of values over a chart's labels.
| Field | Type | Default | Description |
|---|---|---|---|
keyrequired | string | Identifies the series among the chart's others, and marks name it. | |
labelrequired | string | Its name in the tooltip and the screen-reader table, such as "This week". | |
valuesrequired | readonly (number | null)[] | One value per label, in order; null where there isn't one, which leaves a gap. A value that isn't a
finite number, such as NaN, is left out the same way. | |
color | ChartColor | chart-1 | Its color. Defaults to chart-1, chart-2 and on in order, or chart-muted for the comparison. |
comparison | boolean | Marks the series the others are measured against, such as the previous period: it's drawn in
chart-muted under the others, and the tooltip shows the first series' change from it. |
Accessibility
A group named by its title, which is an h3 by default. The info button is named by the explanation its tooltip shows. The chart is a slider over its points, described by the change. The footer's link is named Details for and the title; the expand button repeats it for the pointer only, so it's hidden from screen readers and Tab. While loading the card is marked busy, its skeletons are hidden and its chart's pill isn't read out, so a page of loading cards isn't announced once per card.
| Keys | What they do |
|---|---|
| Enter or Space | Opens what the metric means from the info button, in a popover that Tab or a press elsewhere also closes |
| Left and Right arrows | Step through the chart's points, announcing each one's label, values and change |
| Home or End | Jumps to the chart's first or last point |
| Escape | Closes the info popover, or hides the chart's tooltip |
| Enter | Follows the Details link |
Motion
It changes shape as one surface, on `spring.smooth`, or `spring.morph` for a big change, rather than closing and reopening.
With reduced motion: Its skeletons don't shimmer, and they crossfade into the numbers in 100ms.
Layout
It takes its container's width on a card padded 16px, elevated by default, outline (its edge drawn inside, so its parts line up with an elevated card's), soft, tinted (bg-tint, which its words and chart keep their contrast on) or plain (no surface or padding): the title truncates with its full text in its title, the value is title-lg in tabular figures, or 32px at size lg, the change wraps under it, and the chart is 160px tall. While it loads, each part's skeleton holds that part's place, so nothing moves when the numbers arrive; the info button is 28px square.
Related
See it in the roastery demo's overview.