Usage Meter

A count against a quota — 9 of 40 emails, 3 of 5 seats — drawn as a row of discrete pips, with role="meter" and the full aria-value trio. Not a mode of Progress: a progress bar reports a task advancing, a usage meter reports an allowance already spent.

tsx
import { UsageMeter } from "@pestoui/core"

Default

Under 30 units each pip is exactly one unit, so 9 of 24 is literally 9 lit pips. label names the count — it is appended to the readout, never a replacement for it.

9/24emails

Sizes

sm tightens the pip height and the gutter together, so the two measurements cannot disagree.

3/5seats
3/5seats

Tones

The tone lands on the root as a text colour and every lit pip paints from currentColor. The caption keeps its own foreground colours in every tone.

8/12projects
8/12projects
8/12projects
8/12projects
8/12projects

Over quota

Past the allowance every pip fills, the row turns destructive whatever tone was asked for, and the percentage appears — the caption row is drawn even without a label.

44/40emails110%
6/5120%

Large quotas and no quota

Above 30 units each pip becomes a bucket of max / 30 and the readout carries the exact figure. A quota of zero is treated as no quota: the row stays dark and the meter degrades to role="img" so nothing announces a fake percentage.

640/1000tool calls
1/1000tool calls
12exports

Pips only

With no label and an unspent allowance the caption row is omitted entirely; give the meter an srLabel so it still has a name.

Ticks

variant="ticks" draws fixed-width ticks with the readout inline after them, for a seat count in a dialog footer. The readout follows the pips rule — shown with a label or when over quota — and wraps under the strip in a narrow column.

5/12seats filled
14/12seats filled117%

Bar

variant="bar" is one line broken by an inline caption, for a quota tile that already shows the figures. label is the suffix after the percentage and defaults to "used". With no quota the caption states the count instead.

55% used
93% used

Props

PropTypeDefaultDescription
valuenumber—The count spent. Negative and non-finite values read as 0.
maxnumber—The quota. Zero, negative and non-finite values are treated as no quota at all.
labelReactNode—Visible suffix, never a replacement for the number. pips and ticks append it to the count — "emails" renders "9/40 emails". bar appends it to the percentage and defaults it to "used".
srLabelstring"Usage"The meter's accessible name, e.g. "Monthly email quota". An explicit aria-label wins over it.
tone"selected" | "success" | "warning" | "destructive" | "info" | "muted" | "chart-1" … "chart-5""selected"Colour of the lit pips. Over quota always paints destructive; data-tone reports the painted tone and data-over-quota says why.
size"sm" | "default""default"Pip height and gutter, set together. Ticks are a step taller than the pips and the bar half as tall.
variant"pips" | "ticks" | "bar""pips"pips: a full-width row with the readout above. ticks: fixed ticks with the readout inline after. bar: a continuous line with an inline "40% used" caption and no readout row. ticks and bar emit data-variant; pips emits none.

Pesto UI · 117 documented components