跪拜 Guibai
← All articles
Frontend · APP · Rust

One Line of Code Fixes macOS Tray Icon Color for Every Monitor

By 雨夜寻晴天 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

Cross-platform frameworks like Tauri often abstract away platform-specific capabilities, but this case shows that knowing a single native API can eliminate entire categories of bugs. For any developer building desktop apps with tray icons, Template Image is a zero-cost, bulletproof alternative to manual theme detection — and it works per-monitor out of the box.

Summary

Building a macOS desktop app with Tauri v2, a developer ran into a classic problem: the tray icon color didn't match the system theme. The first instinct was to detect dark mode by reading the `AppleAquaColorVariant` global preference and swap icons accordingly. That approach works on a single display, but breaks immediately on multi-monitor setups — the global preference doesn't reflect per-monitor light/dark mode states.

After trying to listen for system appearance notifications and hitting dead ends with macOS's lack of per-monitor mode APIs, the developer found the real solution: Template Image. macOS has long supported marking icons as "templates," where the system automatically extracts the transparent outline and renders it in the appropriate color — white on dark backgrounds, black on light backgrounds — calculated independently for each monitor.

Tauri exposes this through the `.icon_as_template(true)` method on `TrayIconBuilder`. One line of code replaces all the fragile manual detection logic and handles every edge case, including external monitors with different theme settings. The developer reflects that many platform-level problems already have native solutions — developers just need to know where to look.

Takeaways
Reading `AppleAquaColorVariant` via `defaults read` only returns the global dark/light preference, not per-monitor states.
macOS does not expose a public API to query whether an individual monitor is in dark or light mode.
Template Image is a macOS-native feature that automatically colors icons based on the current environment — white on dark, black on light.
Tauri v2 provides `.icon_as_template(true)` on `TrayIconBuilder` to enable Template Image behavior for tray icons.
The icon file itself should be a white PNG with transparent background; macOS only uses the transparent outline for rendering.
Template Image handles multi-monitor setups correctly because macOS calculates the color per display.
iOS has an equivalent concept with `UIImageTemplate`.
Manual detection approaches inevitably leave edge cases uncovered — native system APIs are more reliable.
Conclusions

The instinct to manually detect and adapt is a common reflex from web development, where the environment is less controlled and native APIs are unavailable.

Tauri's decision to expose `.icon_as_template(true)` as a simple boolean flag is a good example of how framework design can make or break access to platform-specific features.

The fact that macOS doesn't expose per-monitor theme state via a public API suggests Apple intentionally wants developers to use Template Image rather than rolling their own logic.

This pattern — platform provides a declarative solution, developers try imperative workarounds — repeats across many domains (e.g., CSS prefers-color-scheme vs. JS-based detection).

The developer's admission that they were unaware of Template Image despite years of web development highlights a knowledge gap between web and native ecosystems that cross-platform tools like Tauri can help bridge.

Concepts & terms
Template Image
A macOS (and iOS) image rendering mode where the system treats the image as a mask, extracting only the transparent pixel outline and automatically coloring it — typically white on dark backgrounds and black on light backgrounds — without the developer needing to specify the color.
Tauri TrayIconBuilder
A builder API in the Tauri framework for creating system tray icons. It provides methods like `.icon()` to set the icon image and `.icon_as_template(true)` to enable macOS Template Image behavior.
AppleAquaColorVariant
A macOS global preference key that stores the user's selected appearance mode. A value of 6 indicates dark mode, but it reflects the system-wide setting, not per-monitor states.
Source: juejin.cn ↗ Google Translate ↗ Backup ↗