Skip to content

tray: customizable icon styles and percentage text#78

Merged
robinebers merged 5 commits intomainfrom
feat/icon-style-and-text
Feb 6, 2026
Merged

tray: customizable icon styles and percentage text#78
robinebers merged 5 commits intomainfrom
feat/icon-style-and-text

Conversation

@robinebers
Copy link
Copy Markdown
Owner

@robinebers robinebers commented Feb 6, 2026

Adds configurable tray icon styles (bars, circle, text-only) with optional percentage text overlay, replacing the fixed bars-only rendering.

Description

  • New tray icon style picker in Settings with live previews (bars, circle, 83% text-only) and a "Show percentage" toggle
  • SVG rendering engine extended with circle gauge, text-only mode, rounded bar paths with visible remainder tails, and dynamic non-square viewboxes for text
  • Persisted settings (trayIconStyle, trayShowPercentage) with backward-compat migration for old style keys
  • Comprehensive test coverage for pace status, provider card pace indicators, settings persistence, tray SVG generation, and App-level integration

Made with Cursor


Note

Medium Risk
Touches tray icon generation/rendering and persisted settings, including new non-square icon rasterization paths that could regress tray appearance across platforms. Changes are well-covered by added unit/integration tests, lowering the likelihood of silent breakage.

Overview
Adds customizable menu bar icon styles (bars, circle, text-only) and an optional percentage text display, with new persisted settings (trayIconStyle, trayShowPercentage) including backward-compatible migration for older stored values.

Updates App to load/save these preferences, pass them into renderTrayBarsIcon, adjust primary-metric selection (4 bars vs 1), and fall back to the packaged gauge icon when text-only cannot produce a valid percent. The tray SVG/rasterization pipeline is significantly expanded to support circle gauges, text-only rendering, percent-text layout with variable icon widths, and improved bar visuals (rounded paths + visible remainder tails).

Settings UI is updated with a new “Menu Bar Icon” picker with live previews, conditional “Show percentage” toggle, and a renamed usage section heading; the previous “Check for updates” button is removed. Tests are extended across app integration, settings persistence/UI, tray SVG generation, and new pace-status logic + provider card pace indicators.

Written by Cursor Bugbot for commit 915b09e. This will update automatically on new commits. Configure here.


Summary by cubic

Add customizable menu bar icon styles (bars, circle, text-only) with an optional percentage next to the icon. Updates Settings with a live-preview picker and persists choices, replacing the fixed bars-only icon.

  • New Features

    • Tray icon styles: bars, circle, text-only; optional “Show percentage” text (hidden for text-only).
    • Settings: style picker with live previews (“Bars”, “Circle”, “83%”); stored as trayIconStyle and trayShowPercentage with backward-compatible migration.
    • Rendering: SVG engine adds circle gauge, rounded bar fills with visible remainder tails, and dynamic width for percent text; rasterizes non-square icons.
    • App: tray updates immediately on probe results and settings changes; style controls bar count; percentage appears when a valid fraction exists.
    • Tests: added coverage for settings persistence, SVG generation, App integration, pace status logic, and ProviderCard pace indicators.
  • Refactors

    • Removed bar edge divider lines and improved high-percentage visuals to keep a visible tail.
    • Renamed “Usage Display” to “Show Usage As” and removed the “Check for updates” button from Settings.

Written for commit 915b09e. Summary will update on new commits.

robinebers and others added 4 commits February 6, 2026 12:12
…splay

- Added support for multiple tray icon styles: "bars", "circle", and "textOnly".
- Introduced functionality to toggle the display of usage percentage next to the tray icon.
- Updated settings page to allow users to select their preferred tray icon style and visibility of percentage.
- Enhanced tests to cover new tray icon styles and settings functionality.
- Refactored related components to accommodate the new features.
- Changed the text from "Show percentage next to icon" to "Show percentage" in the settings page and related tests for consistency.
- Updated tests to reflect the new text and ensure proper functionality of the percentage toggle feature.
- Enhanced the tray icon rendering logic to accommodate new visual styles and layout adjustments.
- Updated the tray bar rendering logic to remove edge divider lines and ensure a visible tail for high bar percentages.
- Enhanced test cases to reflect changes in SVG output and maintain visual consistency.
- Refactored preview bar layout functions to improve clarity and maintainability, including adjustments to remainder visibility and fill percentage calculations.
Co-authored-by: Cursor <cursoragent@cursor.com>
@macroscopeapp
Copy link
Copy Markdown

macroscopeapp bot commented Feb 6, 2026

Add customizable menu bar icon styles ('bars', 'circle', 'text-only') with optional percentage text and persist settings in src/App.tsx and src/lib/settings.ts

Implement tray icon style and percentage state, persistence, and rendering; update SVG/rasterization to support non-square icons and text; expose controls in Settings and remove update check UI.

📍Where to Start

Start with the tray icon update flow in scheduleTrayIconUpdate and related state in src/App.tsx, then review SVG generation in makeTrayBarsSvg and renderTrayBarsIcon in src/lib/tray-bars-icon.ts.


Macroscope summarized 915b09e.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9a1742bfea

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +178 to +183
export async function loadTrayIconStyle(): Promise<TrayIconStyle> {
const stored = await store.get<unknown>(TRAY_ICON_STYLE_KEY);
// Backward compatibility with older tray style values.
if (stored === "barsWithPercentText" || stored === "barWithPercentText") return "bars";
if (stored === "circularWithPercentText") return "circle";
if (isTrayIconStyle(stored)) return stored;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve old percent-text setting on migration

loadTrayIconStyle maps legacy values like barsWithPercentText/circularWithPercentText to "bars"/"circle", but there is no corresponding migration for trayShowPercentage. In App the show-percentage flag then loads as false (default), so users who previously enabled percent text will silently lose it after upgrade. If you want backward-compatibility, you need to set trayShowPercentage to true when these legacy values are encountered (or migrate the stored value before reading the new key).

Useful? React with 👍 / 👎.

{trayIconStyle !== "textOnly" && (
<label className="mt-2 inline-flex items-center gap-2 text-sm text-foreground">
<Checkbox
key={`tray-show-percentage-${trayShowPercentage}`}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Low

pages/settings.tsx:372 The dynamic key based on trayShowPercentage causes the checkbox to remount on every toggle, breaking keyboard focus. Consider using a static key or removing it entirely.

Suggested change
key={`tray-show-percentage-${trayShowPercentage}`}
<Checkbox

🚀 Want me to fix this? Reply ex: "fix it for me".

Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

if (stored === "circularWithPercentText") return "circle";
if (isTrayIconStyle(stored)) return stored;
return DEFAULT_TRAY_ICON_STYLE;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migration loses percentage text preference from old styles

Medium Severity

The loadTrayIconStyle migration converts old values like barsWithPercentText and circularWithPercentText to bars and circle, but doesn't coordinate with loadTrayShowPercentage to preserve the percentage visibility preference. Since loadTrayShowPercentage independently defaults to false, users migrating from these old WithPercentText styles will silently lose their percentage text setting.

Additional Locations (1)

Fix in Cursor Fix in Web

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 issues found across 10 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/pages/settings.tsx">

<violation number="1" location="src/pages/settings.tsx:83">
P1: Hardcoded colors (`white`/`black`) cause poor contrast in Dark Mode.
When the button is active (`isActive={true}`), it uses `variant="default"`. In Dark Mode, this variant typically has a white/light background.
Rendering white text/icons (`text-white`, `bg-white`) on a white background makes the preview invisible.
Using semantic theme tokens ensures visibility in both modes.</violation>

<violation number="2" location="src/pages/settings.tsx:372">
P2: The dynamic `key` that includes `trayShowPercentage` causes the Checkbox to remount on every toggle, which breaks keyboard focus. Use a static key or remove the key prop entirely since it's not needed for a single checkbox.</violation>
</file>

<file name="src/lib/settings.ts">

<violation number="1" location="src/lib/settings.ts:192">
P2: When migrating legacy tray icon settings the new `loadTrayShowPercentage()` does not infer that older `*WithPercentText` styles implied “show percentage”, so existing users lose their overlay after upgrading.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

{trayIconStyle !== "textOnly" && (
<label className="mt-2 inline-flex items-center gap-2 text-sm text-foreground">
<Checkbox
key={`tray-show-percentage-${trayShowPercentage}`}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The dynamic key that includes trayShowPercentage causes the Checkbox to remount on every toggle, which breaks keyboard focus. Use a static key or remove the key prop entirely since it's not needed for a single checkbox.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/pages/settings.tsx, line 372:

<comment>The dynamic `key` that includes `trayShowPercentage` causes the Checkbox to remount on every toggle, which breaks keyboard focus. Use a static key or remove the key prop entirely since it's not needed for a single checkbox.</comment>

<file context>
@@ -195,6 +333,50 @@ export function SettingsPage({
+        {trayIconStyle !== "textOnly" && (
+          <label className="mt-2 inline-flex items-center gap-2 text-sm text-foreground">
+            <Checkbox
+              key={`tray-show-percentage-${trayShowPercentage}`}
+              checked={trayShowPercentage}
+              onCheckedChange={(checked) => onTrayShowPercentageChange(checked === true)}
</file context>
Fix with Cubic

Comment on lines +192 to +196
export async function loadTrayShowPercentage(): Promise<boolean> {
const stored = await store.get<unknown>(TRAY_SHOW_PERCENTAGE_KEY);
if (typeof stored === "boolean") return stored;
return DEFAULT_TRAY_SHOW_PERCENTAGE;
}
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot Feb 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When migrating legacy tray icon settings the new loadTrayShowPercentage() does not infer that older *WithPercentText styles implied “show percentage”, so existing users lose their overlay after upgrading.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/lib/settings.ts, line 192:

<comment>When migrating legacy tray icon settings the new `loadTrayShowPercentage()` does not infer that older `*WithPercentText` styles implied “show percentage”, so existing users lose their overlay after upgrading.</comment>

<file context>
@@ -158,6 +171,35 @@ export async function saveDisplayMode(mode: DisplayMode): Promise<void> {
+  await store.save();
+}
+
+export async function loadTrayShowPercentage(): Promise<boolean> {
+  const stored = await store.get<unknown>(TRAY_SHOW_PERCENTAGE_KEY);
+  if (typeof stored === "boolean") return stored;
</file context>
Suggested change
export async function loadTrayShowPercentage(): Promise<boolean> {
const stored = await store.get<unknown>(TRAY_SHOW_PERCENTAGE_KEY);
if (typeof stored === "boolean") return stored;
return DEFAULT_TRAY_SHOW_PERCENTAGE;
}
export async function loadTrayShowPercentage(): Promise<boolean> {
const stored = await store.get<unknown>(TRAY_SHOW_PERCENTAGE_KEY);
if (typeof stored === "boolean") return stored;
const legacyStyle = await store.get<unknown>(TRAY_ICON_STYLE_KEY);
if (
legacyStyle === "barsWithPercentText" ||
legacyStyle === "barWithPercentText" ||
legacyStyle === "circularWithPercentText"
) {
return true;
}
return DEFAULT_TRAY_SHOW_PERCENTAGE;
}
Fix with Cubic

…rkaround

- Changed tray icon style classes to use new primary foreground colors for improved visual consistency.
- Added dynamic key workaround for Checkbox components to address rendering issues in Tauri, ensuring proper visibility after toggling.
@robinebers robinebers merged commit 168f23b into main Feb 6, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant