Dots

Usage Meter

Shows progress against a limit or allowance as a bar, a ring or a gauge, with a warning near and over the limit.

Monthly spendingResets Dec 1
Online payments$60 left until Dec 1
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

The UsageMeter component shows how much of a limit is used: card spending, withdrawals, free transfers or data. It shows a label and used-of-total, with an optional line under it. From 90% it turns to warning, and over the limit it stays full. Use it for a quantity that has a ceiling. For a task in progress with no limit, use a progress bar; for levels the user moves through, use TierLadder.

Installation

pnpm dlx shadcn@latest add @dots/usage-meter

Usage

import { UsageMeter } from "@/components/ui/usage-meter"
<UsageMeter
  label="Monthly spending"
  value={1840}
  max={2500}
  formatOptions={{ style: "currency", currency: "USD" }}
  description="Resets Dec 1"
/>

Features

  • Three variants: bar for a list of limits, ring for a row of several, gauge for one limit on its own
  • Three states from the numbers: default, near from warnAt, and over above the limit
  • Any unit through formatOptions, or your own valueText
  • Two sizes
  • Announced as a meter with the used-of-total as its value, plus how much is over the limit

States

The state comes from value and max. From warnAt (90% by default) the fill and the description turn to warning. Above the limit the value text turns to warning too, and the fill stays full.

TransfersResets Dec 1
Online payments$60 left until Dec 1
Cash withdrawal$60 over the limit. New withdrawals are declined until Dec 1.
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

Units

Pass formatOptions for any number format, or valueText for your own wording. Set warnAt={false} for an allowance that is fine to use up, such as free withdrawals.

Mobile dataPlan renews in 9 days
Free withdrawals
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

Sizes

Use size to switch between default and sm.

Daily send
Daily send
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

Gauge

Set variant="gauge" for one limit that leads a screen. The percentage and used-of-total sit inside the arc, with zero and the limit at its ends.

Monthly card limit$1,800 left until Dec 1
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

Ring

Set variant="ring" to show several limits side by side. The percentage sits inside the ring, and the label and used-of-total under it.

Transfers
Online
Cash
"use client"

import { UsageMeter } from "@/components/ui/usage-meter"

Accessibility

UsageMeter is built on React Aria Meter, so it is announced as a meter (role="meter progressbar", with progressbar as the fallback) with its value range. The label names the meter, and the description is linked with aria-describedby. The bar, ring and gauge graphics and the visible numbers are hidden from assistive tech; the value is read once.

Spoken value

Screen readers hear value and max formatted with formatOptions, such as "$1,840 of $2,500", plus how much is over the limit. valueText is only shown, never read. When valueText adds words or a unit the numbers lack, such as a custom unit without formatOptions, pass a valueLabel with the same meaning.

<UsageMeter
  label="Data abroad"
  value={1.2}
  max={2}
  valueText="1.2 GB of 2 GB"
  valueLabel="1.2 GB of 2 GB used"
/>

Meaning beyond color

The warning and over states use color. Say what happens in description, such as "$60 over the limit".

API Reference

UsageMeter

Accepts all React Aria Meter props except children, className, style, value, minValue, maxValue, valueLabel and formatOptions, which are replaced below.

PropTypeDefaultDescription
labelReactNode-What is measured. Also names the meter. Required.
valuenumber-How much is used, in the same unit as max. May exceed it. Required.
maxnumber-The limit or allowance. Required.
valueTextReactNodeboth numbers formattedUsed-of-total text: next to the label on a bar, under the ring, inside the gauge. Not read by screen readers.
formatOptionsIntl.NumberFormatOptions-Number format for the value text, the gauge ends and screen readers.
localestring"en-US"Locale for the numbers.
descriptionReactNode-Quiet line at the bottom.
valueLabelstringused-of-totalWhat screen readers hear as the value.
warnAtnumber | false0.9Share of max from which the meter turns to warning.
variant"bar" | "ring" | "gauge""bar"How the usage is drawn.
size"default" | "sm""default"The meter size.
classNamestring-Additional classes to apply to the root element.

The root element exposes data-state ("default", "near" or "over"), data-variant and data-size for styling.