From 0e0944f3c223245e5c01769b5b8b71425f58f999 Mon Sep 17 00:00:00 2001 From: RCD <90105158+Finesssee@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:48:42 +0700 Subject: [PATCH] Show informational float bar metrics as text The float bar rendered an informational selected metric (no budget set, a balance line, no active session) as "0% used" and turned its text into "Resets ". Pills now show the informational text (or an em dash), keep the neutral tone and only show a reset taken from a timestamp, like the tray card and the tray tooltip already do. --- .../src/floatbar/FloatBar.test.tsx | 81 +++++++++++++++++-- apps/desktop-tauri/src/floatbar/FloatBar.tsx | 27 +++++-- 2 files changed, 95 insertions(+), 13 deletions(-) diff --git a/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx b/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx index 88860e087d..32a0460645 100644 --- a/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx +++ b/apps/desktop-tauri/src/floatbar/FloatBar.test.tsx @@ -327,33 +327,100 @@ describe("FloatBar", () => { it("keeps an informational primary window when no secondary window is available", async () => { tauriMocks.getCachedProviders.mockResolvedValue([ - snapshot("claude", "Claude", 10, { informational: true }), + snapshot("claude", "Claude", 0, { + informational: true, + resetDescription: "No active 5h session", + }), ]); tauriMocks.getSettingsSnapshot.mockResolvedValue(settings()); const { container } = renderFloatBar(bootstrap()); await waitFor(() => { - expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toContain( - "Claude: 10% used", + expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toBe( + "Claude: No active 5h session", ); }); }); it("keeps an informational primary window when the secondary window is informational", async () => { tauriMocks.getCachedProviders.mockResolvedValue([ - snapshot("claude", "Claude", 10, { + snapshot("claude", "Claude", 0, { informational: true, - secondary: { used: 90, informational: true }, + resetDescription: "No active 5h session", + secondary: { used: 90, informational: true, resetDescription: "Weekly unavailable" }, }), ]); tauriMocks.getSettingsSnapshot.mockResolvedValue(settings()); const { container } = renderFloatBar(bootstrap()); await waitFor(() => { - expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toContain( - "Claude: 10% used", + expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toBe( + "Claude: No active 5h session", + ); + }); + }); + + it("shows an informational metric's text instead of a percentage or reset wording", async () => { + tauriMocks.getCachedProviders.mockResolvedValue([ + snapshot("litellm", "LiteLLM", 0, { + informational: true, + resetDescription: "No budget set", + }), + ]); + tauriMocks.getSettingsSnapshot.mockResolvedValue( + settings({ enabledProviders: ["litellm"], floatBarShowResetInline: true }), + ); + + const { container } = renderFloatBar( + bootstrap({ enabledProviders: ["litellm"], floatBarShowResetInline: true }), + ); + await waitFor(() => { + expect(container.querySelector(".floatbar__pill")).not.toBeNull(); + }); + const pill = container.querySelector(".floatbar__pill"); + expect(pill?.getAttribute("title")).toBe("LiteLLM: No budget set"); + expect(pill?.querySelector(".floatbar__pct")?.textContent).toBe("No budget set"); + expect(pill?.textContent).not.toMatch(/%|Resets/); + expect(pill?.querySelector(".floatbar__reset")).toBeNull(); + expect(pill?.classList.contains("floatbar__pill--ok")).toBe(true); + }); + + it("keeps the neutral tone for an informational metric in remaining mode", async () => { + tauriMocks.getCachedProviders.mockResolvedValue([ + snapshot("cursor", "Cursor", 100, { + informational: true, + resetDescription: "$12.40 API-rate", + }), + ]); + tauriMocks.getSettingsSnapshot.mockResolvedValue( + settings({ enabledProviders: ["cursor"], showAsUsed: false }), + ); + + const { container } = renderFloatBar( + bootstrap({ enabledProviders: ["cursor"], showAsUsed: false }), + ); + await waitFor(() => { + expect(container.querySelector(".floatbar__pill")).not.toBeNull(); + }); + const pill = container.querySelector(".floatbar__pill"); + expect(pill?.getAttribute("title")).toBe("Cursor: $12.40 API-rate"); + expect(pill?.classList.contains("floatbar__pill--ok")).toBe(true); + }); + + it("uses an em dash for an informational metric without text and keeps a timestamp reset", async () => { + const resetsAt = new Date(Date.now() + (2 * 60 + 5) * 60_000).toISOString(); + tauriMocks.getCachedProviders.mockResolvedValue([ + snapshot("codex", "Codex", 0, { informational: true, resetsAt }), + ]); + tauriMocks.getSettingsSnapshot.mockResolvedValue(settings()); + + const { container } = renderFloatBar(bootstrap()); + await waitFor(() => { + expect(container.querySelector(".floatbar__pill")?.getAttribute("title")).toMatch( + /^Codex: —\nResets in 2h \d+m$/, ); }); + expect(container.querySelector(".floatbar__pct")?.textContent).toBe("—"); }); it("sorts providers by their selected rate window", async () => { diff --git a/apps/desktop-tauri/src/floatbar/FloatBar.tsx b/apps/desktop-tauri/src/floatbar/FloatBar.tsx index e8d71af8fe..3aea49eeff 100644 --- a/apps/desktop-tauri/src/floatbar/FloatBar.tsx +++ b/apps/desktop-tauri/src/floatbar/FloatBar.tsx @@ -182,6 +182,11 @@ function CostPill({ * Color follows usage: green default, amber when remaining drops below the * high-usage threshold, red when remaining is below the critical threshold * or the provider is exhausted. + * + * An informational metric (no budget set, a balance line, no active session) + * has no quota percentage. Like the tray card and the tray tooltip, the pill + * shows its text instead, keeps the neutral tone, and never turns that text + * into reset wording. */ function ProviderPill({ provider, @@ -207,21 +212,29 @@ function ProviderPill({ stateLabel: string; }) { const rateWindow = provider.selectedMetric; + const informational = rateWindow.isInformational === true; const remaining = Math.max(0, Math.min(100, rateWindow.remainingPercent)); const used = Math.max(0, Math.min(100, rateWindow.usedPercent)); const displayPercent = showAsUsed ? used : remaining; const displaySuffix = showAsUsed ? usedSuffix : remainingSuffix; const state = describeProviderState(provider.errorState); - const exhausted = rateWindow.isExhausted || state.isProblem; let tone: "ok" | "warn" | "crit" = "ok"; - if (exhausted || remaining <= critRemaining) tone = "crit"; - else if (remaining <= highRemaining) tone = "warn"; + if (state.isProblem) tone = "crit"; + else if (!informational) { + if (rateWindow.isExhausted || remaining <= critRemaining) tone = "crit"; + else if (remaining <= highRemaining) tone = "warn"; + } const brand = getProviderIcon(provider.providerId).brandColor; - const label = state.isProblem ? stateLabel : `${Math.round(displayPercent)}%`; + const infoText = rateWindow.resetDescription?.trim() || "—"; + const label = state.isProblem + ? stateLabel + : informational + ? infoText + : `${Math.round(displayPercent)}%`; const resetText = useFormattedResetTime( rateWindow.resetsAt, - rateWindow.resetDescription, + informational ? null : rateWindow.resetDescription, resetRelative, ); const resetSuffix = resetText ? `\n${resetText}` : ""; @@ -237,7 +250,9 @@ function ProviderPill({ title={ state.isProblem ? `${provider.displayName}: ${stateLabel}` - : `${provider.displayName}: ${label} ${displaySuffix}${resetSuffix}` + : informational + ? `${provider.displayName}: ${infoText}${resetSuffix}` + : `${provider.displayName}: ${label} ${displaySuffix}${resetSuffix}` } data-tauri-drag-region style={{ "--brand": brand } as CSSProperties}