Foundations / Style
Color
Markdown crates/theme/src/lib.rs docs.rs
use theme::Theme;
let theme = Theme::of(cx);
div().bg(theme.surface).text_color(theme.text_muted)Theme is a plain struct of gpui::Hsla fields installed as a gpui Global. Components read it at paint time and never take a colour parameter.
Installing
use theme::appearance::{self, AppearanceMode};
appearance::init(AppearanceMode::System, cx);Once at boot, before the first window opens — later than that and the first frame paints in the wrong palette.
Replacing a token
theme::set_palette(|appearance| {
let mut theme = Theme::for_appearance(appearance);
theme.danger = my_red(appearance);
theme
}, cx); // before appearance::initRegister the builder rather than installing one theme: appearance::apply rebuilds the palette from scratch on every light/dark switch, and a theme installed on its own lasts only until then.
API
impl Theme {
/// The installed palette.
pub fn of(cx: &App) -> &Theme;
pub fn for_appearance(appearance: Appearance) -> Self;
// ...
}// theme::appearance
/// Once at boot, before the first window opens.
pub fn init(mode: AppearanceMode, cx: &mut App);
/// Subscribes to the OS notification.
pub fn observe_window(window: &mut Window, cx: &mut App) -> Subscription;
/// Changes the preference and repaints.
pub fn set_mode(mode: AppearanceMode, cx: &mut App);
/// Serde-serializable, so you persist it wherever your settings live.
pub enum AppearanceMode { System, Light, Dark }
// ...Light is designed, not inverted — mirroring lightness reverses surface order, elevation and accent contrast. Each light text token lands within ~0.5 of its dark counterpart's ratio, and a test asserts it. accent is neutral by default: a library that ships a hue puts that hue in every app that installs it.