Cost meter

A live ticker of tokens and dollars for a single run, with a budget cap.

Loading preview…

Install

  1. 1

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

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

Usage & API

Example

cost-meter.tsx
import { CostMeter } from "@/components/ai/cost-meter"

<CostMeter
  inputTokens={1}
  outputTokens={1}
  inputPrice={1}
  outputPrice={1}
  running={true}
  elapsed={1}
/>

Props CostMeter

PropType & descriptionRequired
inputTokensnumberRequired
outputTokensnumberRequired
inputPricenumberDollars per million tokens.Required
outputPricenumberRequired
runningbooleanRequired
elapsednumberRequired
budgetnumberOptional
modelstringOptional
onRun() => voidOptional
onStop() => voidOptional

Dependencies

  • React
  • Tailwind CSS
  • motion
  • lucide-react
Implementation notes

The header is the status dot, the status word, the elapsed seconds, and the model pill. Below that, "This run" labels the large price, with Stop or Run on the right. Stop uses a filled square. Run uses a play icon, and the label flips to "Run again" as soon as outputTokens is greater than zero, even if the run was cancelled early. The budget track is 6 pixels tall, filled with the same blue-to-sand gradient as the usage ring, scaled on the x axis to the clamped ratio. The left caption is the rounded percent of the run budget. The right caption is the cap, "$0.50 cap" at the default. Two bordered cells follow. Input, with an up-right arrow, shows the token count with thousands separators and its dollar share. Output, with a down-left arrow, does the same. The big price itself does not insert separators. The demo starts at zero, so the first paint is "Ready", $0.0000, and 0 percent of a $0.50 cap. After 600 milliseconds it sets input to 18,240 and starts adding output every 100 milliseconds, between 40 and 110 tokens a tick, until 6,840. Around three seconds, one tick also adds 9,420 input tokens, the stand-in for a tool result folded back into the prompt. At the demo prices the finished total is $0.3093, about 62 percent of the default budget, so the clamp never shows. Lower budget, or raise a price, if you need the bar pinned at 100 percent while the headline keeps climbing. Reduced motion drops the dot's pulse and the bar's spring. The digits still update on every render.

Choosing a layout

Put it on a run that can get expensive: a long agent loop, a batch over a large file, or a playground where the bill should be visible before someone starts again. Stop is on the meter while running is true, and it only calls onStop. The component will not halt your stream when the bar fills. You stop the work, then pass running as false and stop updating the counts. Run, or "Run again" once any output tokens exist, calls onRun. That pairing fits a page that can start and cancel one call. The demo does exactly that: a timer owns the numbers, and the meter only displays them.

Leave it off the composer during ordinary chat. Someone sending short messages does not need four decimal places, and Quota banner already says when the plan is nearly gone. Credit top-up is where they buy more balance after a usage-based plan runs out. Use the cost meter when the number that matters is this run, not the month, and when you already have separate input and output counts plus a price for each. One combined token total cannot fill both cards, because each card multiplies by its own rate. If you only know a single blended price, this layout will mislead unless you put the whole cost on one side and leave the other at zero on purpose.

Does crossing the budget stop the run?

No. The ratio is the minimum of 1 and total divided by budget, so the bar and the percent caption stop at full. The dollar headline has no clamp. Below one dollar it stays at four places, and from one dollar up it prints two. Nothing in CostMeter calls onStop when the cap is reached. Stop is only the button, and only while running is true. budget is optional and defaults to 0.5 dollars, not to a token count. The ratio divides by that cap, so keep it above zero: a positive total against a zero cap paints the bar full, and a zero total against a zero cap produces a scale that is not a number.

Why does the demo's input count jump once?

The interval is not only output tokens. Every 100 milliseconds the demo adds 0.1 to elapsed and adds a random output step, capped at 6,840. When elapsed is within 0.05 seconds of 3, that same tick adds 9,420 to input, once, because the step is a tenth of a second wide. inputPrice and outputPrice stay constant for the whole run. CostMeter does not know that a tool result caused the jump. It reprices whatever you pass on the next render, input card and output card separately, then sums them under "This run".