Usage Meter
A labeled meter for a limit: seats 8 of 10, storage 4.2 of 5 GB, API calls. It warns at 80 percent and at the limit with words and an icon, not only color, and can offer an upgrade when near the limit. UsageMeterList shows several. Built on role="meter"; the app owns the numbers. UI permission is not security: the server must check again.
A ready-made piece, built from the library's own parts.
A block puts several components together into something you would otherwise assemble by hand. It never fetches data: you give it the data, or answer its callbacks. It is copied into your project like any component, with the parts it uses, so you can change anything.
Basic
Add people in Members.
Thresholds
Near the limit
Limit reached
Over the limit
List
- Seats8 of 10 seats
Near the limit
- Storage4.2 of 5 GB
Near the limit
- API calls6,200 of 10,000
Resets on 1 March.
States
Permissions
Near the limit
Ask a billing owner to upgrade the plan.ClassNames
Near the limit
Installation
npx rdloom add usage-meterCopies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes.
Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/usage-meter.jsonWorks, but without upgrade tracking.
Usage
import { UsageMeter } from "@rdloom/react";
<div className="flex w-full justify-center">
<div className="w-full max-w-md">
<UsageMeter label="Seats" value={6} limit={10} unit="seats" description="Add people in Members." />
</div>
</div>API Reference
Defined by the spec. Components also accept the props of the React Aria component they wrap.
| Prop | Type | Default |
|---|---|---|
labelrequiredWhat is measured, e.g. "Seats". It is the accessible name. | string | none |
valuerequiredHow much is used. | number | none |
limitrequiredThe most the plan allows. | number | none |
unitA unit shown after the numbers, e.g. "GB" or "seats". | string | none |
formatValueFormats the numbers. Default: up to one decimal. | (value: number) => string | none |
descriptionA line under the meter, e.g. "Resets on 1 April". | string | none |
warningAtThe percentage from which the meter says it is near the limit. | number | 80 |
dangerAtThe percentage from which the meter says the limit is reached. | number | 100 |
onUpgradeShows an upgrade button when the meter is near the limit or over it; yours, async. | () => void | Promise<unknown> | none |
upgradeLabelThe text of the upgrade button. | string | "Upgrade" |
stateloading shows a skeleton and marks the meter busy; the other states show the meter. | DataState | none |
permissionsWhat the app allows: upgrade. Hidden renders nothing; disabled keeps the control reachable (aria-disabled) with the reason shown and read, and nothing runs. This only changes what people see: the server must check again. | Permissions<"upgrade"> | none |
classNamesExtra class names for single parts, so you can restyle one part without editing the file. Keys: root, header, label, value, status, track, bar, description, upgradeButton. | Partial<Record<"root" | "header" | "label" | "value" | "status" | "track" | "bar" | "description" | "upgradeButton", string>> | none |
Accessibility
Role meter, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.
Keyboard
- Tab: moves to the upgrade button when it is shown
Screen readers announce
- "Seats, meter, 8 of 10 seats, near the limit"
- "Storage, meter, 5 of 5 GB, limit reached"
- "Upgrade, button"
What your code must do
- Has role meter with aria-valuemin, aria-valuemax and aria-valuenow, named by the label
- aria-valuetext says the amounts and the status in words, e.g. "8 of 10 seats, near the limit"
- Near the limit and at the limit are told by text and an icon as well as the bar color
- The bar color has 3:1 contrast against the track
- A value above the limit is shown as full and said as over the limit
Block contract
- Data
- A used amount and a limit with an optional unit.
- Data states
- loading, ready
- Permissions
- upgrade
- Events
- onUpgrade
- You can replace
- classNames for each part; warningAt and dangerAt; unit and formatValue; UsageMeterList for several meters
Guidelines
Use it when
- Showing how much of a plan limit is used: seats, storage, API calls
- Nudging an upgrade at the moment people need it
Avoid it when
- Progress of a task that finishes: use Progress
- A trend over time: use Chart or Sparkline
Don't
- Treating the permissions prop as protection: UI permission is not security, so the server must check again
- Computing usage in the component: the numbers are yours
- Showing the warning by color alone: the text and icon are on purpose
Design tokens
The semantic tokens this component uses. Change them once and every component follows; see Design tokens.
--rd-color-action-primary--rd-color-border-default--rd-color-text-default--rd-color-text-muted--rd-color-feedback-warning--rd-color-feedback-danger