Meter
When to use
Section titled “When to use”- Disk or quota usage
- Password strength
- A score or rating within a known range
Not for progress through a task — use a Progress.
Choosing between showing progress, loading or a measurement:
| Component | Use it for | For example |
|---|---|---|
| Progress | A task whose completion is known, moving toward done | Upload at 40%, step 2 of 5 |
| Stepper | The named steps of a multi-step flow, and which one you’re on | Checkout: Cart, Shipping, Payment |
| Meter | A measurement within a known range, not a task | Disk usage, password strength, a score |
| Spinner | Work of unknown length, in a small space | A button saying “Saving…”, a panel refreshing |
| Skeleton | Content still loading whose shape is known, so the layout does not jump | Placeholder rows in a list, a profile card |
import { Meter } from '@arun-dev/ui';
const stack = { display: 'grid', gap: 'var(--space-md)', maxInlineSize: '20rem' };const field = { display: 'grid', gap: 'var(--space-3xs)' };
// Disk usage: low is good, so optimum sits low. Past `high` it turns red.const disks = [ { name: 'Photos', used: 0.3 }, { name: 'Projects', used: 0.68 }, { name: 'Backups', used: 0.92 },];
export default function MeterBasics() { return ( <div style={stack}> {disks.map((disk) => ( <div key={disk.name} style={field}> <label htmlFor={`meter-${disk.name}`}> {disk.name}: {Math.round(disk.used * 100)}% used </label> <Meter id={`meter-${disk.name}`} value={disk.used} low={0.6} high={0.85} optimum={0.1} /> </div> ))} </div> );}Meter is a native <meter>, for a measurement within a known range, such as disk usage or a
password’s strength. low, high and optimum colour it as the browser does:
| Region | Colour | Token |
|---|---|---|
the one optimum is in | good | --meter-optimum-color |
| next to it | fair | --meter-suboptimum-color |
| the far side | poor | --meter-poor-color |
In the example, low usage is best (optimum is low), so usage past high turns red.
Which end is good
Section titled “Which end is good”The colours aren’t tied to high or low values. optimum says which end is good, and the colours
follow it:
| Measurement | Good when | Set optimum | 90% shows |
|---|---|---|---|
| Disk usage | low | below low, e.g. 0.1 | red |
| Average score | high | above high, e.g. 1 | green |
import { Meter } from '@arun-dev/ui';
const stack = { display: 'grid', gap: 'var(--space-md)', maxInlineSize: '20rem' };const field = { display: 'grid', gap: 'var(--space-3xs)' };
// Test scores: high is good, so optimum sits high. Below `low` it turns red.const classes = [ { name: 'Class A', average: 0.9 }, { name: 'Class B', average: 0.62 }, { name: 'Class C', average: 0.35 },];
export default function MeterScores() { return ( <div style={stack}> {classes.map((group) => ( <div key={group.name} style={field}> <label htmlFor={`score-${group.name}`}> {group.name}: {Math.round(group.average * 100)}% average </label> <Meter id={`score-${group.name}`} value={group.average} low={0.5} high={0.75} optimum={1} /> </div> ))} </div> );}Here a high score is best (optimum is 1), so 90% is green, and an average under low turns
red. With optimum between low and high, the middle is good and both ends are fair; neither
end turns red.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | The measurement, between min and max. | |
min | number | 0 | The bottom of the range. |
max | number | 1 | The top of the range. |
low | number | Below this is the low region. With high and optimum, it picks the colour. | |
high | number | Above this is the high region. | |
optimum | number | The best value. Its region is good (success); the next is fair (warning); the far one is poor (error). | |
className | string | Concatenated with the component's own classes, never replacing them. | |
render | ReactElement | Element or component to render instead of the default. Props, className, event handlers and ref are merged onto it. | |
ref | Ref<HTMLElement> | Ref to the rendered element. Merged with any ref on the render element. | |
…rest | HTMLAttributes | Anything else is spread onto the rendered element, so id, aria-*, data-* and event handlers all reach the DOM. |
- Progress through a task is a Progress.
- Name it with a
<label>oraria-label, and put the value in the text.