Skip to content

Commit 9efc88e

Browse files
ryaneggzclaude
andcommitted
fix: address cost tracking frontend review — rename CustomSSEEvent, accessibility, code quality
- Rename CustomEvent to CustomSSEEvent in stream.ts to avoid collision with DOM CustomEvent - Move formatCost to module-level function in CostBadge.tsx - Add aria-label to CostBadge trigger button for accessibility - Make costByPhase required in CostBadgeProps (always provided by useCostTracking) - Add documentation comment for totalInputTokens/totalOutputTokens in useCostTracking Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Signed-off-by: ryaneggz <kre8mymedia@gmail.com>
1 parent 8da693e commit 9efc88e

3 files changed

Lines changed: 20 additions & 11 deletions

File tree

frontend/src/components/chat/CostBadge.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,16 @@ import {
55
PopoverTrigger,
66
} from "@/components/ui/popover";
77

8+
function formatCost(cost: number): string {
9+
if (cost < 0.01) return `$${cost.toFixed(4)}`;
10+
if (cost < 1) return `$${cost.toFixed(3)}`;
11+
return `$${cost.toFixed(2)}`;
12+
}
13+
814
interface CostBadgeProps {
915
totalCost: number;
1016
turnCount: number;
11-
costByPhase?: Record<string, number>;
17+
costByPhase: Record<string, number>;
1218
}
1319

1420
export function CostBadge({
@@ -18,16 +24,13 @@ export function CostBadge({
1824
}: CostBadgeProps) {
1925
if (totalCost === 0) return null;
2026

21-
const formatCost = (cost: number) => {
22-
if (cost < 0.01) return `$${cost.toFixed(4)}`;
23-
if (cost < 1) return `$${cost.toFixed(3)}`;
24-
return `$${cost.toFixed(2)}`;
25-
};
26-
2727
return (
2828
<Popover>
2929
<PopoverTrigger asChild>
30-
<button className="flex h-8 items-center gap-1.5 rounded-full border border-border/60 px-3 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors">
30+
<button
31+
aria-label={`Cost: ${formatCost(totalCost)}, ${turnCount} API calls`}
32+
className="flex h-8 items-center gap-1.5 rounded-full border border-border/60 px-3 text-xs text-muted-foreground hover:bg-accent hover:text-accent-foreground transition-colors"
33+
>
3134
<DollarSign className="h-3.5 w-3.5" />
3235
<span>{formatCost(totalCost)}</span>
3336
<span className="text-muted-foreground/60">&middot;</span>
@@ -45,7 +48,7 @@ export function CostBadge({
4548
<span className="text-muted-foreground">LLM Calls</span>
4649
<span className="font-mono">{turnCount}</span>
4750
</div>
48-
{costByPhase && Object.keys(costByPhase).length > 0 && (
51+
{Object.keys(costByPhase).length > 0 && (
4952
<>
5053
<div className="border-t border-border pt-2 text-xs font-medium">
5154
By Phase

frontend/src/hooks/useCostTracking.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { useState, useCallback } from "react";
22

3+
/**
4+
* Internal state for cost tracking.
5+
*
6+
* `totalInputTokens` and `totalOutputTokens` are tracked here and returned
7+
* from the hook for use by the cost breakdown panel in a future iteration.
8+
*/
39
interface CostState {
410
totalCost: number;
511
turnCount: number;

frontend/src/lib/entities/stream.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export interface AbortedEvent {
7373
data: { reason: string };
7474
}
7575

76-
export interface CustomEvent {
76+
export interface CustomSSEEvent {
7777
type: "custom";
7878
data: {
7979
type: string;
@@ -98,7 +98,7 @@ export type SSEEvent =
9898
| ValuesEvent
9999
| ErrorEvent
100100
| AbortedEvent
101-
| CustomEvent;
101+
| CustomSSEEvent;
102102

103103
export interface DoneSignal {
104104
type: "done";

0 commit comments

Comments
 (0)