Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- **The pointing-hand cursor no longer sticks after a session row disappears under it.** The Capacity Dock's click-to-raise rows pushed the cursor on hover and popped it on exit, but a row that vanishes while hovered — the session leaves the ten-minute window, or the dock hides — never fires an exit, so the pushed cursor stayed on system-wide until something else replaced it. The row now pops what it pushed on the way out. Clicking such a row could also raise the wrong terminal: Claude Code writes a fresh `~/.claude/sessions/<pid>.json` on every resume and never removes the old one, so several files name the same session and the first one the directory happened to list was taken. The newest is now taken instead, and if its pid fails the recycled-pid guard the row stays inert rather than falling back to a stale file.
- **A quota window that resets now refreshes now.** The menubar's 30s tick compared the reset times it already holds — Claude's 5-hour and weekly windows, Codex's two windows, every Capacity Dock provider's — against the previous tick, and forces a refresh for the provider whose window just rolled over instead of leaving the pre-reset percentage on screen for up to five minutes. Each reset instant fires once; everything else keeps the existing cadence.
- **The popover's quota warning can be read in light mode, and says which limit it is warning about.** The banner under the tagline painted its text in the same system yellow, orange or red as its 12% pill, so in light mode warning text measured 1.2:1 to 1.4:1 against the pill, and even red reached only 3.0:1; in dark mode red fell to 3.3:1. The pill keeps its hue, and the text and its glyph now take a per-appearance colour for each severity, a deep amber, rust or brick in light mode and a lifted orange or red in dark mode, that measures 5.3:1 or better everywhere. A test holds every severity at WCAG AA (4.5:1) against the pill composited over both ends of the popover's background in both appearances. The sentence also named no window. Its figure is the provider's worst window, so "Claude 70% of quota used" meant the 5-hour limit while Claude's own panel read weekly 34%, and it looked wrong. It now reads `Claude · 5-hour 71% · resets in 3h 12m`, with the countdown worded exactly as the Capacity Dock words it and one line per provider when several are warning. The countdown is left off when the provider reports no reset time or the reset has already passed. "Over limit" is kept for a window at or past 100%, where it used to cover anything from 90%. The flame's colour and the providers that trigger the banner are unchanged.
- **The Trend tooltip shows the day's total again under its model breakdown.** Provider-filtered history now carries tokens, so with only Claude selected the tooltip header switched to a token count and the day's cost appeared nowhere, and the model rows could not stand in for it because only four of up to five models render. A Total row with the day's cost and tokens now closes the breakdown, as it does in the web dashboard, and the header figure it replaces is shown only for days without a breakdown. Fixes #1433.

## 0.9.24 - 2026-09-04

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@
"Avg/day" = "Avg/day";
"Peak" = "Peak";
"Yesterday" = "Yesterday";
"Total" = "Total";
"%@ tokens" = "%@ tokens";
"%@ on %@" = "%@ on %@";
"Daily activity" = "Daily activity";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@
"Avg/day" = "日均";
"Peak" = "峰值";
"Yesterday" = "昨天";
"Total" = "总计";
"%@ tokens" = "%@ Token";
"%@ on %@" = "%@(%@)";
"Daily activity" = "每日活动";
Expand Down
40 changes: 32 additions & 8 deletions mac/Sources/CodeBurnMenubar/Views/HeatmapSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -344,11 +344,9 @@ private struct BarColumn: View {

private struct BarTooltipCard: View {
let bar: TrendBar
/// Value to display in the tooltip header. Matches the metric the trend chart
/// is currently using (tokens when the .all-providers view has token data,
/// cost when provider-filtered views force a $ fallback). Passing this in keeps
/// the tooltip in sync with the chart instead of always reading bar.tokens,
/// which is zero for provider-filtered days.
/// Value shown in the tooltip header on days without a model breakdown, in
/// the metric the trend chart is using (tokens when the bars carry any, else
/// cost). Days with a breakdown show a Total row instead.
let value: Double
let formatValue: (Double) -> String
@Environment(\.colorScheme) private var colorScheme
Expand Down Expand Up @@ -380,9 +378,11 @@ private struct BarTooltipCard: View {
.font(.system(size: 11, weight: .semibold))
.foregroundStyle(primaryText)
Spacer()
Text("\(formatValue(value))")
.font(.codeMono(size: 10.5, weight: .semibold))
.foregroundStyle(Theme.brandAccent)
if bar.topModels.isEmpty {
Text("\(formatValue(value))")
.font(.codeMono(size: 10.5, weight: .semibold))
.foregroundStyle(Theme.brandAccent)
}
}

if !bar.topModels.isEmpty {
Expand All @@ -407,6 +407,30 @@ private struct BarTooltipCard: View {
.foregroundStyle(tertiaryText)
}
}

Rectangle()
.fill(borderStroke)
.frame(maxWidth: .infinity)
.frame(height: 0.5)

// Day totals from the payload, not a sum of the rows above:
// only four models render and a day can carry more.
HStack(spacing: 6) {
Color.clear
.frame(width: 3, height: 12)
Text(L("Total"))
.font(.system(size: 10, weight: .semibold))
.foregroundStyle(primaryText)
Spacer()
if bar.cost > 0 {
Text(bar.cost.asCompactCurrency())
.font(.codeMono(size: 9.5, weight: .semibold))
.foregroundStyle(Theme.brandAccent)
}
Text("\(formatTokensCompact(bar.tokens)) tok")
.font(.codeMono(size: 9.5, weight: .medium))
.foregroundStyle(tertiaryText)
}
}
}
}
Expand Down
Loading