Token Burn Telemetry

Data & Tables

Live model token consumption, latency, and cost calculator.

Interactive Live Preview
components/ui/token-cost-meter.tsxTypeScript · React 19
1"use client";
2
3import * as React from "react";
4
5interface TokenCostMeterProps {
6 variant?: string;
7}
8
9export default function TokenCostMeter({ variant = "Live" }: TokenCostMeterProps) {
10 const [model, setModel] = React.useState<"claude" | "gpt4o" | "gemini" | "deepseek">("claude");
11 const [promptTokens, setPromptTokens] = React.useState(18400);
12 const [completionTokens, setCompletionTokens] = React.useState(3200);
13
14 const modelRates = {
15 claude: { name: "Claude 3.5 Sonnet", input: 3.0, output: 15.0, ttft: "280ms", tps: "74 tok/s" },
16 gpt4o: { name: "GPT-4o", input: 2.5, output: 10.0, ttft: "310ms", tps: "88 tok/s" },
17 gemini: { name: "Gemini 1.5 Flash", input: 0.075, output: 0.3, ttft: "190ms", tps: "125 tok/s" },
18 deepseek: { name: "DeepSeek R1", input: 0.55, output: 2.19, ttft: "420ms", tps: "42 tok/s" },
19 };
20
21 const selected = modelRates[model];
22 const inputCost = (promptTokens / 1_000_000) * selected.input;
23 const outputCost = (completionTokens / 1_000_000) * selected.output;
24 const totalCost = inputCost + outputCost;
25
26 return (
27 <div className="w-full max-w-105 overflow-hidden rounded-card bg-surface shadow-card border border-line">
28 {/* Header */}
29 <div className="primitive-card-bar flex items-center justify-between border-b border-line bg-surface/90 px-3.5 py-2.5">
30 <div className="flex items-center gap-2">
31 <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="var(--accent)" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
32 <polyline points="22 12 18 12 15 21 9 3 6 12 2 12" />
33 </svg>
34 <span className="font-display font-semibold text-[13.5px] text-ink">
35 Token Burn & Telemetry
36 </span>
37 </div>
38 <span className="rounded-full bg-green/10 text-green px-2 py-0.5 font-mono text-[10.5px] font-medium">
39 Budget: 84% Healthy
40 </span>
41 </div>
42
43 {/* Model Selector Bar */}
44 <div className="grid grid-cols-4 gap-1 border-b border-line bg-inset/40 p-1.5">
45 {(Object.keys(modelRates) as (keyof typeof modelRates)[]).map((key) => (
46 <button
47 key={key}
48 onClick={() => setModel(key)}
49 className={`rounded-[6px] py-1 text-center font-mono text-[11px] transition-all ${
50 model === key ? "bg-surface text-ink shadow-btn font-semibold" : "text-ink-3 hover:text-ink-2"
51 }`}
52 >
53 {key.toUpperCase()}
54 </button>
55 ))}
56 </div>
57
58 {/* Main Metrics Grid */}
59 <div className="grid grid-cols-3 gap-2 p-3.5">
60 <div className="rounded-control bg-inset/60 p-2.5">
61 <span className="font-mono text-[10px] text-ink-3 uppercase">Total Burn</span>
62 <p className="mt-1 font-mono text-[16px] font-bold text-accent">
63 ${totalCost.toFixed(4)}
64 </p>
65 <span className="font-mono text-[10px] text-ink-3/70">
66 {(promptTokens + completionTokens).toLocaleString()} tokens
67 </span>
68 </div>
69
70 <div className="rounded-control bg-inset/60 p-2.5">
71 <span className="font-mono text-[10px] text-ink-3 uppercase">Time to First Tok</span>
72 <p className="mt-1 font-mono text-[16px] font-bold text-ink">
73 {selected.ttft}
74 </p>
75 <span className="font-mono text-[10px] text-green">⚡ Latency Optimal</span>
76 </div>
77
78 <div className="rounded-control bg-inset/60 p-2.5">
79 <span className="font-mono text-[10px] text-ink-3 uppercase">Throughput</span>
80 <p className="mt-1 font-mono text-[16px] font-bold text-ink">
81 {selected.tps}
82 </p>
83 <span className="font-mono text-[10px] text-ink-3/70">Streaming Gen</span>
84 </div>
85 </div>
86
87 {/* Breakdown Sliders / Bars */}
88 <div className="space-y-2 border-t border-line px-3.5 py-3">
89 <div className="flex items-center justify-between text-[11.5px]">
90 <span className="text-ink-2 font-body">Prompt Input (Context Cache)</span>
91 <span className="font-mono text-ink text-[11px]">{promptTokens.toLocaleString()} tok (${inputCost.toFixed(4)})</span>
92 </div>
93 <div className="h-1.5 w-full overflow-hidden rounded-full bg-field">
94 <div
95 className="h-full rounded-full bg-accent transition-all duration-300"
96 style={{ width: `${(promptTokens / (promptTokens + completionTokens)) * 100}%` }}
97 />
98 </div>
99
100 <div className="flex items-center justify-between text-[11.5px] pt-1">
101 <span className="text-ink-2 font-body">Completion Output</span>
102 <span className="font-mono text-ink text-[11px]">{completionTokens.toLocaleString()} tok (${outputCost.toFixed(4)})</span>
103 </div>
104 <div className="h-1.5 w-full overflow-hidden rounded-full bg-field">
105 <div
106 className="h-full rounded-full bg-orange transition-all duration-300"
107 style={{ width: `${(completionTokens / (promptTokens + completionTokens)) * 100}%` }}
108 />
109 </div>
110 </div>
111
112 {/* Footer Guardrail */}
113 <div className="flex items-center justify-between border-t border-line bg-inset/40 px-3.5 py-2 font-mono text-[10.5px] text-ink-3">
114 <span>Hard limit: $50.00 / month</span>
115 <button
116 onClick={() => {
117 setPromptTokens((p) => p + 2500);
118 setCompletionTokens((c) => c + 600);
119 }}
120 className="text-accent hover:underline"
121 >
122 + Simulate Query
123 </button>
124 </div>
125 </div>
126 );
127}
128

Props & Specification

PropTypeDefaultDescription
variantLive | ProjectedLiveVisual state and layout presentation mode.
classNamestring""Optional Tailwind CSS wrapper class overrides.

Related Components in Data & Tables