Usage ring
ProOne usage against its limit as a large ring: the figure in the centre over "of $10", "{percent} used" under it (rounded down below 100 %, as ProgressRing does), and the level in UsageMeters' colours and lines (through usageLevel), said in words with an icon from 75 %, never by colour alone. Over the limit the ring is full and the words keep the measured figure ("$14 of $10", "140 % used"). Where the plan sets no limit there is no ring, only the figure and "No limit set".
Usage that's done but not metered yet (pending) is a striped arc after what's used, said in words, and how far a run may still go past the limit (mayExceedBy) is said under the ring, as UsageMeters has them: your figures, never the ring's.
The pace is the usage's estimate, your own figure: the kit computes none. It is drawn apart from the measured arc, as a thin dashed arc on its own inner track, and said under the ring with its label ("Estimate", or estimateLabel) and its basis in your words (estimateBasis: "at this month's daily average"), never on hover only. With no basis given, the words say none was given.
A figure that isn't known yet (unknown) draws a dashed track and "Not known yet", never an empty ring that reads as zero. paused is your statement that work has stopped (true, or your reason), never inferred from what's used.
The arc runs clockwise from 12 o'clock in every language, as a dial does. In forced colours it is drawn in Highlight on a CanvasText track.
Version 5.4.0· other versions
This page is for 5.4.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0, 1.9.1, 2.0.0, 2.1.0, 2.2.0, 2.3.0, 2.4.0, 2.5.0, 2.5.1, 2.6.0, 2.6.1, 2.6.2, 2.7.0, 2.8.0, 2.9.0, 2.10.0, 3.0.0, 4.0.0, 4.0.1, 4.0.2, 4.1.0, 4.2.0, 4.3.0, 4.4.0, 4.5.0, 5.0.0, 5.1.0 and 5.2.0: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/usage-ring
Brings in: bidi, locale, motion, ops, relative-time, tokens, usage-level, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { UsageRing } from "@/components/candor/usage-ring"
export default function Example() {
return (
<div className="grid w-full gap-8 sm:grid-cols-3">
{/* estimate: your own figure, drawn as a dashed inner arc and said with its basis. The kit computes no pace. */}
<UsageRing
usage={{ label: "Agent spend this month", used: 6.2, limit: 10, unit: "USD", usedText: "$6.20", limitText: "$10", estimate: 8.9, estimateText: "about $8.90" }}
estimateBasis="at this month's daily average"
/>
{/* pending: done but not metered yet; mayExceedBy: your provider's own figure. */}
<UsageRing
usage={{ label: "Agent spend today", used: 9.1, limit: 10, unit: "USD", usedText: "$9.10", limitText: "$10", pending: 0.6, pendingText: "about $0.60", mayExceedBy: 2, mayExceedByText: "$2" }}
paused="Agents stop at the limit"
/>
{/* No limit: the figure alone, no ring. */}
<UsageRing usage={{ label: "Agent runs this week", used: 412, limit: null, unit: "runs" }} />
</div>
)
}<UsageRing>
| Prop | Type | Default | Description |
|---|---|---|---|
| usagerequired | Usage | — | What's used, the limit (null when there is none), the unit, and your `estimate`, `pending` and `mayExceedBy` figures. |
| estimateBasis | string | undefined | — | What the usage's `estimate` rests on, in your words that finish "Estimate: $8.20 …": "at this month's daily average". Shown under the ring. Left out, the words say no basis was given. |
| unknown | boolean | undefined | — | The figure isn't known yet (the provider hasn't reported): a dashed track and "Not known yet", never zero. |
| paused | boolean | string | undefined | — | The app's own statement that work is paused (by the limit, or by a person): true, or the reason in your words. Drawn with an icon under the ring. Never inferred from what's used. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under usageRing in <LocaleProvider strings={{ … }}>; the table is exported as usageRingStrings.
| Key | English |
|---|---|
| usedOfLimit | {used} of {limit} |
| ofLimit | of {limit} |
| percentUsed | {percent} used |
| amount | {value} {unit} |
| noLimit | No limit set |
| notKnown | Not known yet |
| warning | Nearing the limit |
| danger | Close to the limit |
| atLimit | At the limit |
| overLimit | Over the limit |
| estimate | Estimate |
| estimateValue | {label}: {value} {basis} |
| estimateNoBasis | {label}: {value}; no basis given |
| pending | {value} not yet metered |
| mayExceed | May go over the limit by up to {value}. |
| withPending | {used}, {pending} |
| resets | Resets {time}. |
| paused | Paused |
| pausedBecause | Paused: {reason} |
Motion
| Moment | Family | What it does |
|---|---|---|
| fill | fill | The used arc (and the pending one after it) moves from the old measured amount to the new one when it changes while the ring is on screen. The first amount is drawn in place, never swept from empty, and a limit or figure that isn't known shows no arc to move. |
Set with --cd-motion-usage-ring-<moment>-* in your brand file; the families are in the design reference.
Types from other items
The props above take these. Each is defined by another item; import it from the path shown.
- Usage from @/lib/candor/ops
{ label: string; used: number; /** null when there's no limit (the plan sets none). */ limit: number | null; unit: string; resetsAt?: string | undefined; note?: string | undefined; /** * Your own estimate of where it will end, in the same unit (a quote, a forecast), marked on the bar. It is shown as * given and labelled as an estimate; nothing is extrapolated. */ estimate?: number | undefined; /** Words for the estimate marker ("My guess"); defaults to the `usageMeters.estimate` string. */ estimateLabel?: string | undefined; /** * The figures as your server wrote them, shown as they are instead of Candor's number formatting (with the unit * left to you): `used` ("about $4"), `limit` ("$10") and `estimate`. The numbers still place the bar and markers. */ usedText?: string | undefined; limitText?: string | undefined; estimateText?: string | undefined; /** * Work already done that your provider hasn't metered yet, in the same unit: it will count, but isn't in `used`. * Drawn after the used part of the bar, striped, and said in words ("about $1 not yet metered"). */ pending?: number | undefined; /** `pending` as your server wrote it ("about $1"), shown as written. */ pendingText?: string | undefined; /** * How far past the limit this may still go, from your own figure (a provider that checks the limit between steps, a * run already under way), in the same unit. Said under the meter; the meter never works it out. */ mayExceedBy?: number | undefined; /** `mayExceedBy` as your server wrote it, shown as written. */ mayExceedByText?: string | undefined; }