cleanup(theme): swap kGreenToggle #006040 for color.background.success (#3141)#3195
Merged
jensenpat merged 1 commit intoMay 26, 2026
Merged
Conversation
aethersdr#3141) The token landed in PR aethersdr#3130 alongside the Theme Editor work. The dark value is bit-identical to the previous literal (#006040), so dark theme renders identically; light theme :checked now uses the soft mint #c8e8d0 instead of the unreadable saturated dark green on a light surround. Stale "no dark-success-background token" comment also removed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
jensenpat
approved these changes
May 26, 2026
Collaborator
jensenpat
left a comment
There was a problem hiding this comment.
Thank you Nigel for theme fix
ten9876
added a commit
that referenced
this pull request
May 27, 2026
…rrides (#3198) Second control-type carve-out following the slider + knob pattern from [#3188](#3188). References the toggle-buttons bullet under "follow-up sweeps" in [#3184](#3184). ## Why tribes (and not a single namespace) Where sliders have one canonical visual identity (track + fill), toggle buttons carry *semantic* colour: the "ON" state communicates meaning — enable / activate / warning / generic-mode — not just a value. A single `color.toggle.background.checked` token can't represent all four colour tribes that exist in the current codebase (green-success, blue-accent, amber-warning, deep-blue-panel), so the carve-out splits the **checked-state** tokens across three tribes: ```cpp enum class ToggleTribe { Accent, Success, Warning }; ``` Unchecked + disabled state styling is shared across tribes. Only the **Accent** tribe additionally carries per-applet overrides through the v2 scope tree — Success and Warning are semantic and look identical wherever they live. ## Namespaces (16 new tokens, both bundled themes) ``` color.toggle.background ← {color.gray.800} (alias to primitive) color.toggle.foreground ← {color.gray.200} color.toggle.border ← {color.gray.700} color.toggle.background.disabled ← {color.gray.900} color.toggle.foreground.disabled ← {color.gray.600} color.toggle.border.disabled ← {color.gray.900} color.toggle.accent.background.checked ← {color.blue.700} (TX red / RX green / comp amber per applet) color.toggle.accent.foreground.checked ← {color.blue.500} color.toggle.accent.border.checked ← {color.blue.500} color.toggle.success.background.checked ← #006040 / #c8e8d0 color.toggle.success.foreground.checked ← {color.green.500} color.toggle.success.border.checked ← {color.green.500} color.toggle.warning.background.checked ← #5a3a0a / #f5e8d0 color.toggle.warning.foreground.checked ← {color.amber.500} color.toggle.warning.border.checked ← {color.amber.500} ``` Also adds **`color.background.warning`** primitive (dark `#5a3a0a` / light `#f5e8d0`) for tribe symmetry with the existing `color.background.success` (which was added in PR #3130). All aliases resolve **directly to primitives** (single-hop) so the `resolveAlias()` lookup against `m_primitives` succeeds — chained semantic→semantic aliases don't resolve through the current path, which would land the literal `{color.background.1}` string into QSS / `color()` callers and break rendering. Caught and fixed during test development. ## Cascade — root → applet → applet/<name> Per-applet overrides live under `scopes.applet.scopes.<name>.tokens` alongside the existing slider + knob overrides. Single-token override (`background.checked` only) matches the slider precedent of one token per applet: ```json "applet": { "scopes": { "tx": { "tokens": { ..., "color.toggle.accent.background.checked": "{color.red.500}" } }, "rx": { "tokens": { ..., "color.toggle.accent.background.checked": "{color.green.500}" } }, "comp": { "tokens": { ..., "color.toggle.accent.background.checked": "{color.amber.500}" } } } } ``` ## What lands | File | Role | |---|---| | `resources/themes/default-dark.json`, `default-light.json` | Token defs + per-applet overrides + new `color.background.warning` primitive | | `src/core/ThemeManager.cpp` | `seedBuiltinDefaults` extension (16 token seeds + 3 applet-scope overrides) so user themes forked before this PR still resolve correctly | | `src/gui/Theme.h` | `ToggleTribe` enum + `applyToggleButtonStyle(btn, tribe)` helper + template | | `src/gui/CatControlApplet.cpp` | Drop inline `kGreenToggle` constant, route through helper (Success tribe) — single source of truth going forward | | `tests/theme_manager_test.cpp` | Coverage for base + per-tribe + per-applet cascade | | `docs/theming/toggle-button-tokens.md` | Following the slider-knob-tokens.md shape with the migration pattern for the next sweep | ## Why no global QSS rule Unlike sliders, **this PR does NOT add a `QPushButton:checked` rule to `appStylesheetTemplate`**. Every checkable button in the codebase that currently has no explicit `:checked` styling would have suddenly acquired the Accent-tribe look — a subtle but real visual regression for ~30+ sites that aren't part of this sweep. Opt-in via the helper keeps the namespace landing isolated; the global QSS rule can land in the follow-up after per-site auditing. ## Verification (Windows 11, MSVC + Ninja + Qt 6.10.3, branched from `aethersdr/AetherSDR` main at `4ee99f78`) **Unit tests:** - 10/10 new toggle assertions pass — base token validity, per-tribe checked values, per-applet cascade for accent (tx=`#ff4d4d`, rx=`#4dd87a`, comp=`#ffb84d`), success + warning stable across applet scopes, `isOverriddenAt` distinguishes own override from inherited. - The 4 pre-existing failures on this branch (lines 452/454/505/644 — `importThemeFromFile` related) are also present on clean `main` at the same source lines (398/400/451/590 there). **Not introduced here.** Looks like a Windows-vs-CI environment difference around temp dir handling. Happy to investigate separately if useful. **Theme Editor inspection (live cascade):** | Scope | `color.toggle.accent.background.checked` resolved | |---|---| | `root` | `#0070c0` (blue, alias to `{color.blue.700}`) | | `applet/tx` | `#ff4d4d` (red, alias to `{color.red.500}`) — verified in Editor columnar view | | `applet/rx` | `#4dd87a` (green) — verified in Editor | | `applet/comp` | `#ffb84d` (amber) — verified in Editor; columnar view shows root `#0070c0` / applet `inherited` / comp `#ffb84d` | **CatControlApplet helper-driven refactor:** - Default Dark, `:checked` → `#006040` dark green background, `#4dd87a` text/border — identical to pre-PR. - Default Light, `:checked` → `#c8e8d0` soft mint background, `#1a8040` text/border — identical to post-#3195. - Docked + floating variants both verified. - Live theme-switch (Dark↔Light without restart) re-renders cleanly via the helper's `applyStyleSheet` registration. **Cross-test sanity:** ran the full test suite. Other test failures (`async_log_writer_test`, `CAT_Flex_test`, `CAT_TS-2000_test`, `ole_compound_file_test`, `rigctld_test`) are unrelated to theme work and present on clean main — not introduced here either. ## One intentional addition to flag The new helper template includes a `QPushButton:disabled` rule that the original `kGreenToggle` constant didn't have. In practice the Enable CAT button is never set disabled in `CatControlApplet`, so this is invisible there. The addition is intentional — gives every toggle that opts into the helper a consistent disabled appearance using the `color.toggle.*.disabled` tokens. ## Out of scope (follow-up sweep) - **Per-site QSS migration** — `AetherDspWidget`, `AetherialAudioStrip`, `AntennaGeniusApplet`, `AppletPanel`, `ClientChainApplet`, `ClientCompApplet` (bypass toggle), `ClientCompEditor`, etc. Each currently has its own inline `QPushButton:checked` stylesheet; multiple sites per file, each needs a tribe judgement before migration. Mirrors the punt on hardcoded slider sites in #3188. - **Multi-token per-applet overrides** — current override on `applet/tx` only touches `color.toggle.accent.background.checked`; `foreground.checked` and `border.checked` stay at the root blue, which on a red background reads visually inconsistent (red bg + blue border + blue text). Adding `red.700`/`green.700`/`amber.700` primitives, or per-applet overrides of all three checked tokens, is the next design step. Documented in the Out of scope section of `toggle-button-tokens.md`. - **Indicator-style toggles** — `QCheckBox::indicator` / `QRadioButton::indicator` are a different visual primitive, separate namespace + sweep. - **Hover / pressed state tokens** — same deferral as sliders. - **`color.toggle.panel.*` tribe** — `AppletPanel.cpp`'s deep blue `#0a3060` for tab-like toggles doesn't fit Accent / Success / Warning cleanly. A fourth `panel` or `muted` tribe may earn its keep in a later sweep. - **Global `QPushButton:checked` rule** in `appStylesheetTemplate` — per-site auditing first. cc @ten9876 @jensenpat @chibondking 73 Nigel G0JKN 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: Jeremy Fielder <kk7gwy@aethersdr.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #3141.
Summary
Mechanical token swap in
CatControlApplet.cpp::kGreenToggle:background: #006040→background: {{color.background.success}}Why
The literal
#006040was bit-identical to the new dark tokencolor.background.success, so the swap is visually-identical on Default Dark. The original concern was light theme: the hardcoded saturated dark-green on a light surround was unreadable. With the token, light theme now resolves to the soft mint#c8e8d0defined indefault-light.json.Diff
Verification
Built on Windows 11 (MSVC + Ninja + Qt 6) on top of
aethersdr/AetherSDRmain at9f3f1c4c. Smoke-tested both docked and floating CAT Control variants in both bundled themes::checkedbackground#006040(token resolves to bit-identical value)#006040#c8e8d0soft mint#c8e8d0Screenshots of dark
:checked(proof of pixel-identical regression) and light:checked(the legibility fix) available — happy to attach to the description in a follow-up commit comment.Acceptance checklist (from #3141)
#006040literal removed fromkGreenToggleinCatControlApplet.cpp:checkedbutton is now legiblecc @ten9876 @jensenpat
73 Nigel G0JKN
🤖 Generated with Claude Code