Rust crate to detect if dark mode or light mode is enabled
See the codeSupports macOS, Windows, Linux, BSDs, and WebAssembly.
On Linux the XDG Desktop Portal D-Bus API is checked for the color-scheme preference, which works in Flatpak sandboxes without needing filesystem access.
Add to your project:
cargo add dark-light
You can detect the current mode by using the detect function. This function returns a Mode value.
fn main() -> Result<(), dark_light::Error> {
match dark_light::detect()? {
dark_light::Mode::Dark => println!("Dark mode"),
dark_light::Mode::Light => println!("Light mode"),
dark_light::Mode::Unspecified => println!("Unspecified"),
}
Ok(())
}
You can subscribe to theme changes by using the subscribe function. It returns a Watcher that yields a new Mode each time the OS theme changes.
fn main() -> Result<(), dark_light::Error> {
let watcher = dark_light::subscribe()?;
for mode in watcher.iter() {
match mode {
dark_light::Mode::Dark => println!("Dark mode"),
dark_light::Mode::Light => println!("Light mode"),
dark_light::Mode::Unspecified => println!("Unspecified"),
}
}
Ok(())
}
On macOS, theme changes are currently detected by polling once per second rather than through a native notification, since the objc2 bindings this crate uses don't yet expose a safe way to observe NSDistributedNotificationCenter.
With the default async-io feature (or tokio) enabled, stream returns a futures_core::Stream of Mode.
use futures_util::StreamExt;
async fn watch_theme() -> Result<(), dark_light::Error> {
let mut stream = dark_light::stream()?;
while let Some(mode) = stream.next().await {
println!("{mode:?}");
}
Ok(())
}
Licensed under either of the following licenses:
101 followers · starred Feb 2022
512 followers · starred Feb 2025
24 followers · starred Oct 2024
83 followers · starred Dec 2024
Rust crate to detect if dark mode or light mode is enabled
See the codeSupports macOS, Windows, Linux, BSDs, and WebAssembly.
On Linux the XDG Desktop Portal D-Bus API is checked for the color-scheme preference, which works in Flatpak sandboxes without needing filesystem access.
Add to your project:
cargo add dark-light
You can detect the current mode by using the detect function. This function returns a Mode value.
fn main() -> Result<(), dark_light::Error> {
match dark_light::detect()? {
dark_light::Mode::Dark => println!("Dark mode"),
dark_light::Mode::Light => println!("Light mode"),
dark_light::Mode::Unspecified => println!("Unspecified"),
}
Ok(())
}
You can subscribe to theme changes by using the subscribe function. It returns a Watcher that yields a new Mode each time the OS theme changes.
fn main() -> Result<(), dark_light::Error> {
let watcher = dark_light::subscribe()?;
for mode in watcher.iter() {
match mode {
dark_light::Mode::Dark => println!("Dark mode"),
dark_light::Mode::Light => println!("Light mode"),
dark_light::Mode::Unspecified => println!("Unspecified"),
}
}
Ok(())
}
On macOS, theme changes are currently detected by polling once per second rather than through a native notification, since the objc2 bindings this crate uses don't yet expose a safe way to observe NSDistributedNotificationCenter.
With the default async-io feature (or tokio) enabled, stream returns a futures_core::Stream of Mode.
use futures_util::StreamExt;
async fn watch_theme() -> Result<(), dark_light::Error> {
let mut stream = dark_light::stream()?;
while let Some(mode) = stream.next().await {
println!("{mode:?}");
}
Ok(())
}
Licensed under either of the following licenses:
101 followers · starred Feb 2022
512 followers · starred Feb 2025
24 followers · starred Oct 2024
83 followers · starred Dec 2024