Usage meter
Shows how much of a plan limit has been used and when it resets, as a ring or a week of daily bars.
Loading preview…
Install
- 1
Run this command in your Tailwind CSS project. It adds
components/ai/usage-meter-ring.tsxand installs its dependencies.$ npx shadcn@latest add https://gradientdeck.com/ai-components/r/usage-meter-ring.json
Usage & API
Example
import { UsageRing } from "@/components/ai/usage-meter-ring"
<UsageRing
used={1}
limit={1}
resetsIn={1}
/>Props UsageRing
| Prop | Type & description | Required |
|---|---|---|
used | number | Required |
limit | number | Required |
resetsIn | numberSeconds until the window resets. | Required |
label | string | Optional |
unit | string | Optional |
size | number | Optional |
Dependencies
- React
- Tailwind CSS
- motion
- lucide-react
Implementation notes
UsageRing draws a square SVG at size, default 148, with a 12 pixel stroke. A gradient runs from blue through violet and pink into sand, and the id of that gradient is unique per instance. The track is a full circle. The value arc uses round caps and a dash offset from the full circumference down to the clamped ratio of used over limit, so a count past the limit still paints as full rather than wrapping. The svg is rotated so the arc starts at the top. aria-valuetext is the percent plus "% used". Nothing in the ring is a button. Pass label, unit, and size when the plan is not a five-hour message window. The demo passes only used, limit, and resetsIn, waits 200 milliseconds, then sets used to 162, which is 81 percent and therefore "Running low" in amber. The layout stacks on a narrow card and sits side by side from the small breakpoint.
Example
import { UsageBar } from "@/components/ai/usage-meter-bar"
<UsageBar
series={[]}
days={[]}
limit={1}
/>Props UsageBar
| Prop | Type & description | Required |
|---|---|---|
series | Series[] | Required |
days | Day[] | Required |
limit | numberWeekly allowance in the same unit as the values. | Required |
unit | string | Optional |
title | string | Optional |
resetsOn | string | Optional |
Dependencies
- React
- Tailwind CSS
- motion
Implementation notes
UsageBar totals each series across every day, adds those totals, and rounds a percent of limit that cannot pass 100. The thin meter carries role="meter", named from title plus "usage", and its segment widths are each series total divided by limit. Leftover allowance stays empty track. If the week runs past limit, the percent text still caps at 100 while the segments can overflow and get clipped. Under that, each day is a button. Column height is the day total over the peak day, times 80 pixels, with a 4 pixel floor so a quiet day does not vanish. A zero value for a series is omitted from that column. The demo days are Mon through Sun and the limit is 5,000 credits. Thursday is the peak, with Code at 420 and Agents at 210. Sunday is only Chat at 25. The button name is the day, its total, and the unit. While a day is active the legend numbers switch from week totals to that day's values, including an explicit 0 where a series did nothing, and the subtitle is aria-live polite. title, unit, and resetsOn are the three strings to replace when the plan is not weekly credits. The demo waits 150 milliseconds, showing a 280 pixel spacer, before it mounts UsageBar.
Choosing a layout
Put the ring where someone is about to spend more of the allowance: a sidebar, an account menu, or the corner of a long thread. It answers how much of this window is left and names the reset, so the cap reads as a time rather than a sudden error. Do not put a dollar total here. Cost meter already prices one run, input against output, under a budget cap, and it has its own stop control. Do not use the ring as the interruption either. Quota banner is the warning card, the limit-reached alert, and the strip that sits on the composer.
Use the bar on a usage or billing page, when the useful question is which day and which kind of work spent the week. The demo series are Chat, Code, Agents, and Images, each with its own color, stacked inside every column and again as a thin total across the top. Hovering or focusing a column dims the rest, and the subtitle switches from the reset day to that column's label and total. The legend follows, showing the active day's values instead of the week. Blur, or a pointer leaving the row, clears the selection. If you only have one number and a countdown, ship the ring and keep the bar for the week.
Does the ring count tokens by itself?
No. Neither export calls a tokenizer. unit on UsageRing is a label, default "messages", and the demo sets used to 162 and limit to 200. UsageBar defaults unit to "credits" and the demo sets limit to 5,000. Plans are often sold in tokens, which is why the meter is searched that way, but the only figures on screen are the ones you pass. resetsIn is seconds until the window resets, and it is independent of used. While an hour or more remains, those seconds are not shown. The hours format is "2h 14m", not a digital clock.
Which total moves when a day column is hovered?
The week stays put. The large used-over-limit figure and the thin stacked meter keep summing every series on every day. Only the subtitle and the legend move to the active day. Series ids in the demo are chat, code, agents, and images, matched against each day's values record. A missing id counts as zero, which is why Tuesday has no Images slice and Saturday has no Agents slice, even though the legend will print 0 for that series while the day is active. Clearing the hover puts the subtitle back to "Resets " plus resetsOn.