Meter
A bounded reading: your figure in large italic above a dimension line, one accent index locating it between its limits. Space remains space; nothing fills it in.
Report an issue with MeterExample
28 GB available for the next project
At the minimum
At the maximum
A signed range
Right to left
Localized figures
A decimal reading
Install
Run it in a project that has the shadcn CLI set up. It brings the 0nlyType base along.
npx shadcn@latest add https:// thedirectors.agency/ ui/ r/meter.jsonUsage
This example also uses Select.
npx shadcn@latest add https:// thedirectors.agency/ ui/ r/ select.json"use client"import * as React from "react"import { Meter } from "@/components/ui/meter"import { Select } from "@/components/ui/select"const projects = { "Film archive": 72, "Identity archive": 38, "Empty archive": 0, "Full archive": 100 }export default function Example() {const [project, setProject] = React.useState<keyof typeof projects>("Film archive")return (<div className="grid w-full max-w-xl gap-12"><Select label="Read the storage in" value={project} onChange={(e) => setProject(e.target.value as keyof typeof projects)}>{Object.keys(projects).map((name) => <option key={name}>{name}</option>)}</Select><Meter label="Storage used" value={projects[project]} max={100} unit=" GB" note={`${100 - projects[project]} GB available for the next project`} /></div>)}Contract
- Underneath: native
<meter>, named by a native<label>. A known reading within limits, such as storage used or a budget balance; use progress for completion and slider for input. - Anatomy:
.ot-meterholding.ot-meter-label,.ot-meter-scale(the visual reading, rule, index and two limits, allaria-hidden), a visually hidden native meter, and optional.ot-meter-note. Every part carriesdata-slot. - Creative move: Paul Rand's dimension lines. A large italic figure stands above a hairline between two end ticks; one accent index marks the exact reading. The empty measure stays empty. The space on either side of the figure shares the remaining width in proportion to the reading, keeping it inside both limits without measuring in script. Longer readings step down from ff toward mf to fit their measure, using the formatted length and container width; exceptionally long text still wraps in flow above the line rather than covering it. Labels and notes wrap too. Units and limits are roman; the reading is yours, in italic.
valueis clamped to finiteminandmax, shared by the visible reading and native meter. Negative ranges work; non-finite values, an overflowing span and max not greater than min throw a RangeError.formatsets all three figures andunitfollows them as supplied.low,highandoptimumretain the native semantics without introducing another colour.- The formatted reading names the value through
aria-valuetext; callers can override it. The note joins any suppliedaria-describedby.id,refand other native meter props reach the meter;className,style,hidden,dirandlangapply to the root. It is a reading, with no tab stop or keyboard interaction. - Motion: legato. When the reading changes, one eased number drives the space around the figure and the index at moderato, so they glide together and an interrupted update continues from the current position; there is no entrance or autonomous loop. Reduced motion changes directly. Flex and logical positioning mirror the scale in right to left, including a locally overridden direction. Readings and limits use left-to-right
bdi, so even a signed number without a lettered unit keeps its sign before the number; localized text retains its own bidi marks. Forced colours keeps the index in Highlight.
Props
| Prop | Type | Default | What it does |
|---|---|---|---|
label | ReactNode | What is measured. A native label names the meter. | |
value | number | The reading, clamped to the range in both the display and the native meter. Must be finite. Use Progress for work being completed, and Slider for a value the reader can set. | |
min / max | number | 0 / 100 | Finite limits with max greater than min. Negative ranges work. Invalid ranges throw a RangeError rather than displaying a misleading scale. |
unit | string | "" | Written as supplied after every figure: " GB" with its space, "%" without. The reading is italic; its unit and the scale limits are roman. |
format | (value: number) => string | en-GB, up to two decimals | Formats the reading and both limits, such as a localized number or currency. Long figures scale down to the mf step, then wrap if needed. Choose the precision and locale explicitly when they matter. |
note | ReactNode | Context beneath the scale, also included in the native meter's accessible description. | |
Native meter props | meter props | id, ref, low, high, optimum and aria attributes reach the native meter. aria-valuetext can supply a more descriptive reading; aria-describedby is joined with the note. className, style, hidden, dir and lang apply to the outer div. |
Craft
Where its move comes from
| Component | Reference | Move |
|---|---|---|
| Meter | Paul Rand dimension lines | An italic reading above an empty measure, one index between its limits |
How it moves
| Component | Articulation | What moves |
|---|---|---|
| Meter | Legato | A changed figure and its index glide to their new places, then rest |