Skip to content

Add high-contrast mode for inactive displays - #2210

Merged
steipete merged 7 commits into
steipete:mainfrom
zpmdd:agent/high-contrast-inactive-displays
Jul 16, 2026
Merged

Add high-contrast mode for inactive displays#2210
steipete merged 7 commits into
steipete:mainfrom
zpmdd:agent/high-contrast-inactive-displays

Conversation

@zpmdd

@zpmdd zpmdd commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add an opt-in Improve visibility on inactive displays toggle under Settings > Menu Bar for the Icon & percent style
  • render the status item image and metric as a single attributed title with NSTextAttachment when enabled
  • disable the control for other icon styles and gate the effective renderer to Icon & percent while preserving the stored preference when switching styles
  • keep the existing AppKit image/title path as the default and restore it immediately when the toggle is disabled
  • persist the setting, localize it across all 23 supported locales, and cover the settings/rendering paths with tests

Context

On multi-display macOS setups, AppKit dims standard NSStatusBarButton image/title content quite aggressively on inactive displays. A three-display comparison on macOS 26.5.2 showed that template images embedded in an attributed title remain significantly more legible.

macOS still applies some system-level inactive-display dimming, so this is an opt-in readability improvement rather than a promise that applications can force an absolutely identical active/inactive appearance. The scope is intentionally limited to Icon & percent, which is the renderer covered by the live visual proof below. See #2190 for the original user screenshot and request.

Visual proof

Tested from a freshly built bundle at b3a64eb (CodexBar 0.43.1 (105)) on macOS 26.5.2 (25F84) with three extended displays and mirroring disabled.

Active/inactive displays, Dark/Light appearances, toggle off/on

The matching inactive-display crops show median non-background pixel luminance increasing from about 35 to 115 in Dark appearance and from about 34 to 113 in Light appearance (roughly 3.3×). The active-display appearance remains visually unchanged.

CodexBar live validation in Dark and Light appearances on active and inactive displays

Menu-open/highlighted and toggle-off restoration

Top: the status item is highlighted with its menu open. Bottom: the same inactive display with high contrast off (left, native dimming restored) and then on again (right, readability restored). The captures are cropped to the menu bar and CodexBar card only.

Menu-open highlighted state and inactive-display toggle restoration

Warning-flash compatibility

This side-by-side artifact was rendered through the production quotaWarningFlashImage and highContrastButtonTitle methods using the real Codex brand asset. The one-off export harness was removed after capture and is not part of the patch.

Normal high-contrast status item and quota warning flash rendering

The live setting was restored to enabled after the off/on check. No real quota notification was manufactured; the warning path was exercised through the production renderer and focused automated tests instead.

Validation

  • merged current main into the PR branch and resolved the changelog conflict without rebasing or force-pushing
  • DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer make check passed (SwiftFormat clean; SwiftLint: 0 violations in 1450 files)
  • focused post-merge tests: 41/41 passed across PreferencesPaneSmokeTests, StatusItemAnimationSignatureTests, and StatusItemQuotaWarningFlashTests
  • the focused coverage now verifies that the preference is available only for Icon & percent, switching to Critters uses the native renderer, and switching back restores the stored high-contrast behavior
  • make test stopped after retrying one unrelated, environment-dependent existing test: browser uninstall invalidates cookie source immediately; on this Mac, Launch Services finds another registered Chrome installation after the test simulates uninstall, and both BrowserDetection.swift and BrowserDetectionTests.swift are identical to current origin/main
  • packaged and code-signature-verified an isolated Debug app with Keychain access and provider refreshes disabled for the original live proof
  • compared the toggle off/on on three extended displays in both Dark and Light appearances; the inactive-display icon and metric changed from heavily dimmed dark gray to a substantially brighter, readable rendering

Closes #2190

@zpmdd

zpmdd commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Live validation update

I tested the freshly built PR branch (b3a64eb; local app version 0.43.1 (105)) on the original setup:

  • macOS 26.5.2 (25F84)
  • 3 extended displays, mirroring disabled
  • Dark and Light appearances
  • active and inactive displays
  • preference both off and on

Results:

  • On inactive displays, enabling the preference makes both the provider icon and usage percentage substantially more legible in both appearances. In the matching target crops below, median non-background pixel luminance increased from about 35 to 115 in Dark appearance and from about 34 to 113 in Light appearance (roughly 3.3×).
  • On the active display, the off/on result is visually unchanged; I observed no meaningful regression to the normal active-display appearance.
  • macOS still applies some system-level dimming, but the metric remains readable without moving focus to that display.
  • The native rendering path remains the default because the preference is off by default.
  • I have been running this local build with the option enabled and am satisfied with the result.

After testing, I restored Dark appearance and left the preference enabled.

CodexBar live validation in Dark and Light appearances on active and inactive displays

@zpmdd
zpmdd marked this pull request as ready for review July 16, 2026 07:33
@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed July 16, 2026, 1:40 PM ET / 17:40 UTC.

Summary
Adds a persisted, default-off high-contrast renderer for the Icon & percent menu bar style on inactive displays, with settings UI, 23 localizations, and focused tests.

Reproducibility: not applicable. as a bug reproduction: this PR implements a new optional rendering mode, and its observable benefit is demonstrated with fresh-bundle multi-display screenshots.

Review metrics: 3 noteworthy metrics.

  • Changed surface: 33 files, +363/-30. The implementation is moderate in aggregate but mostly additive and narrowly scoped.
  • Localization coverage: 23 locale files updated. The permanent settings copy is provided across every supported locale rather than falling back to English.
  • Focused validation: 41/41 focused tests passed. The reported suites cover settings availability, rendering signatures, cache healing, and warning-flash behavior.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #2190
Summary: This PR is the explicit implementation candidate for the linked inactive-display readability request.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦞 diamond lobster
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦞 diamond lobster
Result: ready for maintainer review.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Next step before merge

  • No automated repair is needed because the current head has no actionable correctness finding and only requires normal check completion and merge review.

Security
Cleared: The diff changes native UI rendering, UserDefaults state, localizations, and tests without altering dependencies, workflows, permissions, credentials, downloads, or release execution paths.

Review details

Best possible solution:

Land the default-off, Icon & percent-scoped implementation after required checks complete, then let the merge close the linked feature request.

Do we have a high-confidence way to reproduce the issue?

Not applicable as a bug reproduction: this PR implements a new optional rendering mode, and its observable benefit is demonstrated with fresh-bundle multi-display screenshots.

Is this the best way to solve the issue?

Yes. Keeping native rendering as the default while narrowly enabling the attributed-title path for Icon & percent is the most compatibility-preserving solution supported by the proof.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against f9993821856e.

Label changes

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P3: This is a default-off readability enhancement with limited blast radius rather than an urgent regression or blocked core workflow.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): Fresh-bundle screenshots directly demonstrate improved inactive-display readability across three displays, both appearances, toggle restoration, and highlighted rendering.
  • proof: sufficient: Contributor real behavior proof is sufficient. Fresh-bundle screenshots directly demonstrate improved inactive-display readability across three displays, both appearances, toggle restoration, and highlighted rendering.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. Fresh-bundle screenshots directly demonstrate improved inactive-display readability across three displays, both appearances, toggle restoration, and highlighted rendering.
Evidence reviewed

What I checked:

Likely related people:

  • steipete: Directly added four follow-up commits on this branch, including three fixes to the affected status-item rendering and cache behavior. (role: recent feature contributor and likely merger; confidence: high; commits: 464035ccedc4, 660d725644e0, 740e9c3fee23; files: Sources/CodexBar/StatusItemController+Animation.swift, CHANGELOG.md)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.
Review history (4 earlier review cycles)
  • reviewed 2026-07-16T04:17:38.531Z sha b3a64eb :: needs real behavior proof before merge. :: none
  • reviewed 2026-07-16T07:41:25.236Z sha b3a64eb :: found issues before merge. :: [P2] Gate the toggle to the rendering style it affects
  • reviewed 2026-07-16T09:20:53.050Z sha b3a64eb :: found issues before merge. :: [P2] Scope the toggle to the renderer it actually controls
  • reviewed 2026-07-16T10:46:20.788Z sha ea2ead5 :: needs maintainer review before merge. :: none

zpmdd commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

The PR body now contains inspectable, redacted proof for every state requested by the latest review:

  • fresh-bundle three-display comparison across Dark/Light, active/inactive, and preference off/on
  • menu-open / highlighted status-item capture
  • toggle-off restoration of the native renderer, followed by re-enabling the readable result
  • warning-flash output rendered through the production methods, plus fresh focused results: StatusItemQuotaWarningFlashTests 3/3 and StatusItemAnimationSignatureTests 14/14

The prior review's reviewed_at timestamp (04:17 UTC) predates the first visual-evidence upload (07:32 UTC), so please evaluate the current PR body and attachments.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Jul 16, 2026

zpmdd commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the P2 style-scope finding in 8efdc02 and merged current main in ea2ead5:

  • the setting row now explicitly identifies Icon & percent and is disabled for Critters/Bars
  • the effective high-contrast renderer is gated to Icon & percent as well, while the stored preference is preserved when switching styles
  • switching to Critters now has focused coverage for the native image path, and switching back verifies that high-contrast content is restored
  • post-merge focused tests passed: 41/41 across the preferences, render-signature, and warning-flash suites
  • make check passed with SwiftLint reporting 0 violations in 1450 files
  • the previous merge conflict is resolved without a rebase or force-push

The full make test runner still reproduces one unrelated environment-dependent BrowserDetectionTests failure on this Mac; the production and test files involved are identical to current origin/main, and the PR body now records the exact result.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jul 16, 2026

Copy link
Copy Markdown

🦞👀
ClawSweeper picked this up.

Command router queued. I will update this comment with the next step.

@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels Jul 16, 2026
@clawsweeper clawsweeper Bot added rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Jul 16, 2026
@steipete
steipete merged commit 6ffdfeb into steipete:main Jul 16, 2026
8 checks passed
@steipete

Copy link
Copy Markdown
Owner

Merged as 6ffdfeb.

Verification:

  • Audited the complete 34-file diff and all 23 locale changes. High-contrast rendering is gated by the opt-in preference and Icon & percent style, remains unavailable for Critters/Bars, and restores the native image/title path when disabled.
  • Added cache self-healing fixes at 660d725, 740e9c3, and be6f80e.
  • Focused Swift tests passed: 147 tests across 5 suites, followed by StatusItemAnimationSignatureTests 15/15 after the final cache fix.
  • make check passed: locale validation, SwiftFormat, and SwiftLint with 0 violations.
  • Final autoreview completed with no actionable findings.
  • Exact head be6f80e passed GitGuardian, lint, changes, both Linux CLI jobs, lint-build-test, and both macOS shards. macOS shard durations: 26m59s and 31m29s.
  • GitHub reported MERGEABLE/CLEAN immediately before merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: keep menu bar usage visible on inactive displays

2 participants