Skip to content

Commit d207b49

Browse files
waterdrop86claude
andcommitted
feat: show both tokens and cost bar charts in AI Cost section
Add a second DailyBarChart (amber) for cost alongside the existing tokens chart (emerald), each with inline label and rolling rollups. Also add billion-scale formatting to formatTokens. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 39961b0 commit d207b49

2 files changed

Lines changed: 42 additions & 18 deletions

File tree

src/renderer/components/Dashboard/CostSection.tsx

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ function formatCost(usd: number): string {
2323
}
2424

2525
function formatTokens(n: number): string {
26+
if (n >= 1_000_000_000) return `${(n / 1_000_000_000).toFixed(1)}B`;
2627
if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
2728
if (n >= 1_000) return `${(n / 1_000).toFixed(1)}K`;
2829
return String(n);
@@ -143,7 +144,8 @@ function CostSection({
143144
dateLabel,
144145
}: CostSectionProps): React.JSX.Element {
145146
const cost = dailyUsage?.estimatedCostUsd ?? 0;
146-
const rollups = computeRollups(tokenHeatmap, e => e.inputTokens + e.outputTokens);
147+
const tokenRollups = computeRollups(tokenHeatmap, e => e.inputTokens + e.outputTokens);
148+
const costRollups = computeRollups(tokenHeatmap, e => e.estimatedCostUsd);
147149
const messageCount = dailyUsage?.messageCount ?? 0;
148150
const premiumRequests = dailyUsage?.premiumRequests ?? 0;
149151
const topSessions = dailyUsage?.topSessions ?? [];
@@ -220,16 +222,44 @@ function CostSection({
220222
/>
221223
)}
222224

223-
{/* Daily bar chart */}
225+
{/* Tokens bar chart */}
224226
{tokenHeatmap.length > 0 && (
225-
<DailyBarChart
226-
entries={tokenHeatmap}
227-
getValue={e => e.inputTokens + e.outputTokens}
228-
getTooltip={(date, v) => `${date}: ${formatTokens(v)} tokens`}
229-
colorScale="emerald"
230-
selectedDate={viewDate}
231-
onSelect={onHeatmapSelect}
232-
/>
227+
<div>
228+
<div className="flex items-center justify-between mb-1">
229+
<span className="text-[10px] text-text-muted uppercase tracking-wide">Tokens</span>
230+
<span className="text-[10px] text-text-muted">
231+
7d: {formatTokens(tokenRollups.d7)} · 30d: {formatTokens(tokenRollups.d30)} · 90d: {formatTokens(tokenRollups.d90)}
232+
</span>
233+
</div>
234+
<DailyBarChart
235+
entries={tokenHeatmap}
236+
getValue={e => e.inputTokens + e.outputTokens}
237+
getTooltip={(date, v) => `${date}: ${formatTokens(v)} tokens`}
238+
colorScale="emerald"
239+
selectedDate={viewDate}
240+
onSelect={onHeatmapSelect}
241+
/>
242+
</div>
243+
)}
244+
245+
{/* Cost bar chart */}
246+
{tokenHeatmap.length > 0 && (
247+
<div>
248+
<div className="flex items-center justify-between mb-1">
249+
<span className="text-[10px] text-text-muted uppercase tracking-wide">Cost</span>
250+
<span className="text-[10px] text-text-muted">
251+
7d: {formatCost(costRollups.d7)} · 30d: {formatCost(costRollups.d30)} · 90d: {formatCost(costRollups.d90)}
252+
</span>
253+
</div>
254+
<DailyBarChart
255+
entries={tokenHeatmap}
256+
getValue={e => e.estimatedCostUsd}
257+
getTooltip={(date, v) => `${date}: ${formatCost(v)}`}
258+
colorScale="amber"
259+
selectedDate={viewDate}
260+
onSelect={onHeatmapSelect}
261+
/>
262+
</div>
233263
)}
234264

235265
{/* Model breakdown */}
@@ -267,13 +297,6 @@ function CostSection({
267297
</div>
268298
)}
269299

270-
{/* Rolling rollups */}
271-
{tokenHeatmap.length > 0 && (
272-
<div className="text-xs text-text-muted">
273-
7d: {formatTokens(rollups.d7)} · 30d: {formatTokens(rollups.d30)} · 90d: {formatTokens(rollups.d90)}
274-
</div>
275-
)}
276-
277300
{/* Usage Quota — Claude-specific (Anthropic API) */}
278301
{(() => {
279302
// Quota comes from the Anthropic API — only relevant for Claude

src/renderer/components/shared/DailyBarChart.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ const COLORS: Record<string, { bar: string; avg: string }> = {
77
green: { bar: '#4ade80', avg: '#86efac' },
88
emerald: { bar: '#34d399', avg: '#6ee7b7' },
99
blue: { bar: '#60a5fa', avg: '#93c5fd' },
10+
amber: { bar: '#fbbf24', avg: '#fcd34d' },
1011
};
1112

1213
interface DailyBarChartProps<T extends { date: string }> {
1314
entries: T[];
1415
getValue: (entry: T) => number;
1516
getTooltip: (date: string, value: number) => string;
16-
colorScale?: 'green' | 'emerald' | 'blue';
17+
colorScale?: 'green' | 'emerald' | 'blue' | 'amber';
1718
selectedDate: string;
1819
onSelect: (date: string) => void;
1920
days?: number;

0 commit comments

Comments
 (0)