Meter
A reading inside a known range: storage used, a plan's quota, a battery. It shares Progress's bar, and adds role="meter", locale-aware formatting and thresholds that recolour the fill.
Installation#
Usage#
Pass value, and min and max when the range is not 0 to 100. A bare <Meter /> renders just the bar; give it an aria-label.
import {
Meter,
MeterLabel,
MeterValue,
MeterTrack,
MeterIndicator,
} from "@/components/ui/meter"
export function Example() {
return (
<Meter value={64}>
<MeterLabel>Storage</MeterLabel>
<MeterValue />
<MeterTrack>
<MeterIndicator />
</MeterTrack>
</Meter>
)
}Anatomy#
import {
Meter,
MeterLabel,
MeterValue,
MeterTrack,
MeterIndicator,
} from "@/components/ui/meter"
<Meter>
<MeterLabel />
<MeterValue />
<MeterTrack>
<MeterIndicator />
</MeterTrack>
</Meter>Meter vs Progress#
Progress reports how far a task has got: an upload, an import. It only moves forward and it ends. A meter reports how much of something there is: disk used, seats taken, charge left. It can go down as well as up, and nothing is ever finished. Screen readers hear the difference (role="progressbar" against role="meter"), so pick by meaning, not by look. The two share one bar, so they always sit together cleanly.
Plan usage#
Quotas in a card. Each meter turns warning past 75% and destructive past 90%, and MeterValue phrases the limit next to the reading.
Thresholds#
low, high and optimum work as on the HTML <meter>. They split the range into an optimal, a suboptimal and a critical region, and the fill takes success, warning and destructive. Put optimum at 0 when lower is better (a disk), at the top when higher is better (a battery). The root carries the region as data-level.
Formatted values#
format takes Intl.NumberFormat options and drives both the readout and aria-valuetext. Without it, the reading is a whole percentage of the range; a percent style reads the share of the range too. The visitor’s locale applies after hydration, so the server render never disagrees with the browser. Pass locale to fix one.
Live readings#
The fill glides between readings on the motion tokens, and the readout uses tabular figures so it never jitters as the number changes.
Sizes#
The Progress height scale: xs (4px), sm (the default), md and lg.
Tones#
For a reading with no good or bad side, pin the colour with tone. It wins over the thresholds.
Accessibility#
The root is role="meter" with aria-valuenow, aria-valuemin, aria-valuemax and an aria-valuetext built from format. A composed MeterLabel names it; otherwise pass aria-label. MeterValue is hidden from assistive tech so the reading is not announced twice. Colour is never the only signal: keep the value visible when a threshold matters.
API reference#
Meter
The root. Renders a <div role="meter"> laid out as a two column grid: label left, value right, track across both. With no children it renders a bare track. Forwards all native <div> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| value* | number | - | The reading. Clamped to min and max for display and for aria-valuenow. |
| min | number | 0 | Lower bound of the range. |
| max | number | 100 | Upper bound of the range. |
| low | number | min | Upper bound of the low region. |
| high | number | max | Lower bound of the high region. |
| optimum | number | midpoint | The ideal reading. Decides which region is optimal, as on the HTML <meter>. |
| format | Intl.NumberFormatOptions | - | Formats the readout and aria-valuetext. Without it, a whole percentage of the range. A percent style also reads the share of the range. |
| locale | Intl.LocalesArgument | - | Locale for the readout. Defaults to the visitor's, applied after hydration (en-US on the server). |
| getAriaValueText | (formattedValue: string, value: number) => string | - | Phrase the screen reader text yourself. An explicit aria-valuetext still wins. |
| size | "xs" | "sm" | "md" | "lg" | "sm" | Bar height: 4, 6, 8 or 12px. The Progress scale. |
| tone | "brand" | "foreground" | "success" | "warning" | "destructive" | "info" | - | Pins the indicator colour. Without it the thresholds pick one, or brand when there are none. |
| Data attribute | Description |
|---|---|
| data-level | "optimal", "suboptimal" or "critical". Only set when low, high or optimum is passed. |
MeterLabel
The visible name. When composed in, it also becomes the meter's accessible name through aria-labelledby. Forwards all native <span> props.
MeterValue
The readout, in tabular figures and aria-hidden (the root already carries it as aria-valuetext). Forwards all native <span> props.
| Prop | Type | Default | Description |
|---|---|---|---|
| children | (formattedValue: string, value: number) => ReactNode | - | Phrase the readout yourself: "45.2 GB of 100 GB". Defaults to the formatted value. |
MeterTrack
The groove, Progress's track slot. Spans both grid columns. Forwards all native <div> props.
MeterIndicator
The fill, Progress's indicator slot. Its width is the reading's share of the range and it glides on change. Forwards all native <div> props.
| Data attribute | Description |
|---|---|
| data-level | Mirrors the root's level, when thresholds are set. |