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. 1

    Run this command in your Tailwind CSS project. It adds components/ai/usage-meter-ring.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/usage-meter-ring.json

Usage & API

Example

usage-meter-ring.tsx
import { UsageRing } from "@/components/ai/usage-meter-ring"

<UsageRing
  used={1}
  limit={1}
  resetsIn={1}
/>

Props UsageRing

PropType & descriptionRequired
usednumberRequired
limitnumberRequired
resetsInnumberSeconds until the window resets.Required
labelstringOptional
unitstringOptional
sizenumberOptional

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.

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.