From 0690be5656d99478ef3901c2691e70f88093ab60 Mon Sep 17 00:00:00 2001 From: gatsby74 <166927047+gatsby74@users.noreply.github.com> Date: Wed, 15 Jul 2026 23:12:12 +0200 Subject: [PATCH] fix(status-bar): sync usage meters with display mode (#8582) * fix(status-bar): sync usage meters with display mode * docs(status-bar): correct barColor comment now that fill follows display mode --------- Co-authored-by: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> --- .../src/components/status-bar/StatusBar.tsx | 22 ++++++++---- .../status-bar/inline-usage-bars.test.tsx | 7 ++-- .../src/components/status-bar/tooltip.test.ts | 34 +++++++++---------- .../src/components/status-bar/tooltip.tsx | 11 +++--- 4 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/renderer/src/components/status-bar/StatusBar.tsx b/src/renderer/src/components/status-bar/StatusBar.tsx index 2c9a2fb979c..b3fc9cb54f3 100644 --- a/src/renderer/src/components/status-bar/StatusBar.tsx +++ b/src/renderer/src/components/status-bar/StatusBar.tsx @@ -81,6 +81,7 @@ import { } from '@/runtime/runtime-provider-accounts-client' import { translate } from '@/i18n/i18n' import { + getDisplayedUsagePercentage, normalizeUsagePercentageDisplay, type UsagePercentageDisplay } from '../../../../shared/usage-percentage-display' @@ -944,15 +945,21 @@ function ClaudeSwitcherMenu({ } // --------------------------------------------------------------------------- -// Mini progress bar (shows consumption / % used, grey) +// Mini progress bar (follows the selected usage percentage meaning, grey) // --------------------------------------------------------------------------- -function MiniBar({ usedPct }: { usedPct: number }): React.JSX.Element { +function MiniBar({ + usedPct, + display +}: { + usedPct: number + display: UsagePercentageDisplay +}): React.JSX.Element { return (
) @@ -972,8 +979,6 @@ export function InlineUsageBars({ const display = normalizeUsagePercentageDisplay( useAppStore((state) => state.usagePercentageDisplay) ) - // Why: the preference changes copy, while bar fill stays consumption-based - // so empty/green and full/red keep the meter semantics introduced in #8167. const usageWindows = [ limits.session ? { @@ -1008,9 +1013,10 @@ export function InlineUsageBars({ {usageWindows.map((window) => (
+ {/* Why: fill follows the selected percentage; color still signals consumption urgency. */}
@@ -1231,7 +1237,9 @@ export function ProviderSegment({ return ( - {p.session && !compact && } + {p.session && !compact && ( + + )} {visibleWindows.map((window, index) => ( {index > 0 && ·} diff --git a/src/renderer/src/components/status-bar/inline-usage-bars.test.tsx b/src/renderer/src/components/status-bar/inline-usage-bars.test.tsx index 404caa344dc..00d27391e62 100644 --- a/src/renderer/src/components/status-bar/inline-usage-bars.test.tsx +++ b/src/renderer/src/components/status-bar/inline-usage-bars.test.tsx @@ -71,7 +71,7 @@ describe('InlineUsageBars', () => { expect(markup).toContain('42% used Fable') }) - it('shows remaining copy without reversing consumption meter fill', async () => { + it('shows remaining copy and remaining meter fill', async () => { mocks.usagePercentageDisplay = 'remaining' const { InlineUsageBars } = await import('./StatusBar') @@ -82,6 +82,9 @@ describe('InlineUsageBars', () => { expect(markup).toContain('68% left 5h') expect(markup).toContain('84% left wk') expect(markup).toContain('58% left Fable') - expect(markup).toContain('width:32%') + expect(markup).toContain('width:68%') + expect(markup).toContain('width:84%') + expect(markup).toContain('width:58%') + expect(markup).not.toContain('width:32%') }) }) diff --git a/src/renderer/src/components/status-bar/tooltip.test.ts b/src/renderer/src/components/status-bar/tooltip.test.ts index 6daf47a8c1c..87e12d66048 100644 --- a/src/renderer/src/components/status-bar/tooltip.test.ts +++ b/src/renderer/src/components/status-bar/tooltip.test.ts @@ -514,26 +514,24 @@ describe('ProviderPanel reset rendering', () => { expect(markup).not.toContain('140%') }) - it.each(PROVIDER_IDS)( - 'applies remaining copy to %s while retaining consumption bar direction', - (providerId) => { - const p = provider({ - provider: providerId, - status: 'ok', - session: { - usedPercent: 25, - windowMinutes: 300, - resetsAt: null, - resetDescription: null - } - }) + it.each(PROVIDER_IDS)('applies remaining copy and meter fill to %s', (providerId) => { + const p = provider({ + provider: providerId, + status: 'ok', + session: { + usedPercent: 25, + windowMinutes: 300, + resetsAt: null, + resetDescription: null + } + }) - const markup = renderToStaticMarkup(ProviderPanel({ p, usagePercentageDisplay: 'remaining' })) + const markup = renderToStaticMarkup(ProviderPanel({ p, usagePercentageDisplay: 'remaining' })) - expect(markup).toContain('75% left') - expect(markup).toContain('width:25%') - } - ) + expect(markup).toContain('75% left') + expect(markup).toContain('width:75%') + expect(markup).not.toContain('width:25%') + }) }) describe('clampUsedPercent', () => { diff --git a/src/renderer/src/components/status-bar/tooltip.tsx b/src/renderer/src/components/status-bar/tooltip.tsx index 849dc7beda3..2a45500ddb8 100644 --- a/src/renderer/src/components/status-bar/tooltip.tsx +++ b/src/renderer/src/components/status-bar/tooltip.tsx @@ -13,6 +13,7 @@ import { } from './usage-error-copy' import { clampUsedPercent, + getDisplayedUsagePercentage, type UsagePercentageDisplay } from '../../../../shared/usage-percentage-display' import { formatUsagePercentageLabel } from './usage-percentage-label' @@ -184,8 +185,8 @@ export function getWindowSections( // `text-background` for primary text and `text-background/50` for secondary // to stay readable inside the inverted tooltip container. -// Why: color-coded by consumption so users can quickly gauge urgency. -// Matches common harness usage meters (Claude/Codex): bars fill with % used. +// Why: color always tracks % used so urgency reads correctly even when the meter +// fills with % remaining (#8560) — low remaining still turns red, not green. // Green = comfortable (<60% used), yellow = caution (60-80%), red = critical (≥80%). export function barColor(usedPct: number): string { if (usedPct < 60) { @@ -278,18 +279,18 @@ export function ProviderPanel({ if (!w) { return null } - // Why: preference changes the copy only; consumption-based bar direction - // preserves the empty/green to full/red meter convention from #8167. const usedPct = clampUsedPercent(w.usedPercent) + const displayedPct = getDisplayedUsagePercentage(usedPct, usagePercentageDisplay) const resetLabel = w.resetsAt ? formatResetCountdown(w.resetsAt - Date.now()) : null return (
{label}
+ {/* Why: fill follows the selected percentage; color still signals consumption urgency. */}