Meter
A Base UI Meter for a measured value in a known range: storage used, strength, a level on an ordinal scale. Never use a meter for an unbounded value.
import { Meter, MeterPanel } from '@fairgarden-private/design/components/Meter'
Meters are ink only: track edges, indicators, cells, ticks and labels all use the scope's step-12 ink, and the track interior shows the ground. No part uses the secondary scale, so a meter never reads as a chart series. The value is always in text.
Kinds in a meter panel
Kinds in a meter panel
bar is the default: an outlined 8 px track with a solid indicator. threshold draws a 12 px tick across the track at a limit, and nearing or passing it is a status glyph plus words (▲ "Near limit", ◆ "Over limit"), never an indicator color swap. steps draws one outlined cell per unit. ordinal is a 1 px scale with a tick and caps label per stop (stops); the active stop is bold, one step larger and pointed to by an outlined triangle. ring is a 2 px arc beside its value.
MeterPanel stacks meters and is their container: label, track and value share one row once the panel is at least 768 px wide, and stack below that. Ordinal labels wrap in narrow panels, and all of them are kept.
'use client'
import { Meter, MeterPanel } from '@fairgarden-private/design/components/Meter'
const gigabytes = new Intl.NumberFormat('en-US', { maximumFractionDigits: 1 })
/** A meter panel: storage near its limit, an ordinal difficulty scale, segmented cells and a ring. */
export function MeterKinds() {
return (
<MeterPanel>
<Meter
label="Photo storage"
value={9.4}
max={10}
threshold={9}
formatValue={(_formatted, value) => `${gigabytes.format(value)} of 10 GB`}
status="warning"
statusText="Near limit"
/>
<Meter kind="ordinal" label="Trail difficulty" value={2} stops={['Easy', 'Moderate', 'Hard', 'Strenuous']} />
<Meter
kind="steps"
label="Volunteer shifts"
value={3}
max={5}
formatValue={(_formatted, value) => `${value} of 5`}
/>
<Meter kind="ring" label="Seed bank" value={72} />
</MeterPanel>
)
}
In print
Linear and segmented values print as a 45° hatch inside their outline, closed by an edge at the value, with the numeral, threshold tick and status words kept. Rings and ordinal scales print as line, with the active label in bold.
API Reference
Meter
A Base UI Meter drawn in ink only: every part is --primary12 on the
ground; the value is always in text. In print, linear and segmented
indicators turn to a 45° hatch inside their outline, closed by an edge at
the value; rings and ordinal scales print as line.
| Prop | Type | Description |
|---|---|---|
label | | The label, in caps ( |
value | | The measured value, between |
formatValue | | Formats the visible value ( |
kind | |
|
primary | | Primary Radix scale: track, indicator, ticks, stops and text. Never defaulted; omitted, it inherits the scope [D133]. |
secondary | | Secondary Radix scale: unused, so a meter never reads as a chart series. Never defaulted. |
status | | The status beside the value; always with |
statusText | | The status word: “Near limit”, “Over limit”. In a form it is also the Field description. |
stops | |
|
threshold | | A limit, drawn as a --ds-space-12 tick at --border-size-2 across the track ( |
MeterPanel
A meter or scale panel: stacks its meters and is the meter-panel
container, so each meter sets label | track | value in one row from
768 px of the panel’s width, and stacks below it.
Additional types
MeterPanelProps
Props for MeterPanel: div props.
type MeterPanelProps = React.ComponentPropsWithRef<'div'>MeterProps
Props for Meter: Base UI Meter Root props plus the kind and color axes, the label, stops, threshold and status.
type MeterProps = {
/** The measured value, between `min` and `max`; for `ordinal`, the index of the active stop. */
value: number;
/**
* `bar` (default): an outlined 8 px track with a solid indicator. `steps`:
* one outlined 12 px cell per unit (`max` − `min` cells). `ordinal`: a
* 1 px track with a tick and a caps label per stop, the active stop bold,
* larger and pointed to. `ring`: a 2 px arc beside its value.
*/
kind?: 'bar' | 'steps' | 'ordinal' | 'ring' | null;
/**
* Primary Radix scale: track, indicator, ticks, stops and text. Never
* defaulted; omitted, it inherits the scope [D133].
*/
primary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| null;
/** Secondary Radix scale: unused, so a meter never reads as a chart series. Never defaulted. */
secondary?:
| 'ruby'
| 'olive'
| 'sage'
| 'slate'
| 'sand'
| 'gray'
| 'mauve'
| 'brown'
| 'bronze'
| 'gold'
| 'red'
| 'crimson'
| 'tomato'
| 'pink'
| 'plum'
| 'indigo'
| 'iris'
| 'violet'
| 'purple'
| 'amber'
| 'blue'
| 'cyan'
| 'grass'
| 'green'
| 'jade'
| 'lime'
| 'mint'
| 'orange'
| 'sky'
| 'teal'
| 'yellow'
| null;
/** The label, in caps (`type-label`); author it in sentence case. */
label?: React.ReactNode;
/** Formats the visible value (`type-data`): "62%", "4.2 of 10 GB". Default: the Base UI formatted value. */
formatValue?: (formattedValue: string, value: number) => React.ReactNode;
/**
* `ordinal` only: the stop labels in order (author them in sentence case;
* CSS sets the caps). `min` becomes 0 and `max` the last index.
*/
stops?: React.ReactNode[];
/** A limit, drawn as a --ds-space-12 tick at --border-size-2 across the track (`bar`). */
threshold?: number;
/** The status beside the value; always with `statusText`. */
status?: MeterStatus;
/** The status word: "Near limit", "Over limit". In a form it is also the Field description. */
statusText?: React.ReactNode;
}meterStatus
The status part: a §1.5.4 glyph plus a word, in the status scale [D129].
type meterStatus = meterStatusMeterStatus
A status beside the value: warning ▲ “Near limit”, danger ◆ “Over limit”, success ●.
type MeterStatus = 'success' | 'warning' | 'danger'Specification: DESIGN-SYSTEM.md §10.18 (progress and meter) and §8.9 (meters, scales and data progress).