HabMeter
A pill progress track whose color is derived from its value.
<HabMeter :value="412" :max="480" label="Seats used" value-text="412 / 480" />The color is an assertion
100% reads success, 70% and above reads accent, 40% and above reads warning, and below that reads error. That encodes "more is better" — right for coverage, wrong for consumption.
<HabMeter :value="18" invert label="Seats used" value-text="18 / 100 seats" />invert flips the scale for quota, spend and capacity. Without it, 18% of seats used renders as an alarm.
tone="neutral" drops the judgement altogether and fills with --hab-chart-muted. It is deliberately not the accent: the accent is also the "70% and above, healthy" band, so the tone that removes meaning would otherwise be the same pixel as one that asserts it.
color overrides the thresholds entirely, for a value whose color comes from elsewhere.
The readout, and the name
They are two different props, and the distinction is easy to get wrong.
label names what is being measured — Seats used — and is never rendered. It is the meter's accessible name, and nothing else.
valueText is the text beside the bar: prefer 412 / 480 over a percentage, since the raw numbers usually answer the next question too. It is also announced in place of the bare number, so a screen reader says "412 / 480" rather than "412". showPercent falls back to a rounded percentage when there is no valueText. Both readouts are tabular, so a column of meters aligns.
Passing the reading as label is the mistake to avoid — this page and every demo did it before the split, which named a control 412 / 480 and left nobody able to tell what it measured.
Accessibility
- Carries a real
role="meter"witharia-valuenow,aria-valueminandaria-valuemax, so the value is announced rather than inferred from a bar's width. The design contract renders only the bar. - Give it a
label, and make it a name rather than a reading. It becomes the meter's accessible name; without one the role is announced with a number and no indication of what is being measured, and the component warns. The reading goes invalueText, which is announced asaria-valuetext. - The color must not be the only thing carrying the judgement. "82%" and a warning fill say the same thing twice on purpose — a color-blind reader gets only the number.
- The fill transitions on
--hab-dur-value, the duration for something moving to a new value.
API
Props
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | undefined | Overrides the threshold color entirely. Any CSS color. |
height | number | 8 | Track height in px. |
invert | boolean | false | Flips the scale for a quantity where less is better — seats used, quota spent, capacity. Without it, 20% of seats used renders as an alarm. |
label | string | undefined | The meter's accessible NAME — what is being measured. Seats used, Coverage, Storage. It is not rendered: a meter sits under a heading or beside a row that already names it on screen, and repeating that is noise. valueText is the visible half. |
max | number | 100 | — |
showPercent | boolean | false | Shows a rounded percentage when there is no valueText. |
tone | "neutral" | undefined | neutral drops the judgement: the fill becomes --hab-chart-muted and the value asserts nothing about whether it is good. |
value | number | 0 | — |
valueText | string | undefined | Text to the right of the bar — the value in the caller's own units, e.g. 412 / 480. Also announced in place of the raw number. Falls back to a percentage when showPercent is set. |