Skip to content

feat: fix menu bar colors not showing on macOS 26 (Liquid Glass)#16

Merged
johnlarkin1 merged 2 commits into
mainfrom
feat-support-menu-bar-coloring-macos26
Mar 19, 2026
Merged

feat: fix menu bar colors not showing on macOS 26 (Liquid Glass)#16
johnlarkin1 merged 2 commits into
mainfrom
feat-support-menu-bar-coloring-macos26

Conversation

@johnlarkin1
Copy link
Copy Markdown
Owner

Important

This PR was created by Claude Code. Take an extra sec to review. Or don't and trust the robots and process.

Summary

  • Fix menu bar color-coded icons (green/orange/red) not displaying on macOS 26 (Tahoe) due to Liquid Glass overriding contentTintColor on template images.
  • Modernize deprecated AppKit drawing APIs across the icon rendering pipeline.

Motivation & Context

macOS 26 introduces "Liquid Glass" for the menu bar, which changes how template images are composited. CodexBar's color pipeline (IconRenderer draws monochrome template + StatusItemController applies contentTintColor) is broken because Liquid Glass overrides/ignores contentTintColor on template images. This means all usage icons appear monochrome regardless of usage level.

Key Changes

  • Bake colors into non-template images on macOS 26+: When tintColor is provided, IconRenderer.renderImage() composites the color over the drawn alpha mask using .sourceIn blend mode and sets isTemplate = false. On older macOS, the existing contentTintColor path is unchanged.
  • macOS 26 branching in applyIcon(): Both unified and per-provider icon paths pass tintColor directly to IconRenderer on macOS 26+, clearing contentTintColor. Brand icons get a similar treatment via tintedBrandImage().
  • Appearance change handling: Non-template images don't auto-adapt to dark/light mode. Added KVO observer on NSApp.effectiveAppearance to re-render icons when appearance changes (macOS 26+ only).
  • Icon cache key update: Added tintHash field (RGBA quantized to 256 buckets per channel) to prevent cache collisions between tinted and untinted icons.
  • Deprecated API modernization:
    • lockFocus/unlockFocusNSImage(size:flipped:drawingHandler:) (3 locations + 1 test)
    • .deviceRGB.calibratedRGB for consistent cross-display rendering
    • NSColor(deviceRed:)NSColor(red:green:blue:alpha:) with explicit CGFloat conversion

Critical Files Touched

File Changes
Sources/CodexBar/IconRenderer.swift .calibratedRGB, removed lockFocus fallback, added tintColor param + cache key
Sources/CodexBar/StatusItemController+Animation.swift macOS 26 branching in both applyIcon() methods, tintedBrandImage() helper, modernized brandImageWithStatusOverlay
Sources/CodexBar/StatusItemController+SwitcherViews.swift NSColor(red:) fix, modernized paddedImage
Sources/CodexBar/StatusItemController.swift Appearance change observer for icon re-rendering
Tests/CodexBarTests/StatusItemAnimationTests.swift Modernized test helper to match production code

How to Test

  • swift build passes
  • swift test passes (all existing tests, no regressions)
  • ./Scripts/lint.sh lint passes (0 violations)
  • Manual testing on macOS 26: Color-coded icons should show green/orange/red correctly in the menu bar under Liquid Glass, including brand icon mode and dark/light mode transitions
  • Manual testing on macOS 14/15: Existing behavior unchanged (template + contentTintColor path)

Additional Notes to Human Reviewer

  • The #available(macOS 26, *) branching follows the existing pattern used in CodexbarApp.swift
  • Loading/morph animations remain monochrome template images (no tint applied) — no change needed
  • Cache cardinality is managed by quantizing tint color to 256 buckets per RGBA channel

Co-authored-by: Claude Code noreply@anthropic.com

johnlarkin1 and others added 2 commits March 19, 2026 07:26
macOS 26 Liquid Glass overrides contentTintColor on template images in
the menu bar, breaking CodexBar's color-coded usage icons. On macOS 26+,
bake the tint color directly into image pixels using sourceIn compositing
and set isTemplate=false. On older macOS, keep the existing template +
contentTintColor approach unchanged.

Also modernizes deprecated APIs:
- Replace lockFocus/unlockFocus with NSImage(size:flipped:drawingHandler:)
- Replace deviceRGB with calibratedRGB for consistent rendering
- Replace NSColor(deviceRed:) with NSColor(red:green:blue:alpha:)
- Add appearance change observer to re-render on dark/light mode switch

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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