Dark Mode
Register and switch light and dark themes at runtime in a GPUI application.
1herogpui::theme::toggle_light_dark(cx);Registering both appearances
ThemeProvider::init(cx) registers the provider with light and dark, so both themes are available without extra setup. Initialize it before opening the first window; rendering a themed component before initialization panics. To boot into dark, start from the dark theme instead:
1gpui_platform::application().with_assets(HeroGpuiAssets).run(|cx: &mut App| {
2 ThemeProvider::init(cx); // registers light + dark
3 // or ThemeProvider::init_with(Theme::dark(), cx);
4 // ...open windows
5});Every theme, including your own, is registered under an id. Activating one repaints every open window. Customization covers building one.
Toggling at runtime
toggle_light_dark(cx) switches between the light and dark defaults. Call it from a menu item, keybinding or gallery control. Every themed component re-renders on the next frame.
Try it live
The gallery (cargo run -p herogpui-gallery) has the toggle in its top bar, and HEROGPUI_THEME=dark boots it straight into dark.Switching to a registered theme
use_theme(id, cx) activates one of the registered themes by id — "light", "dark", or a custom one you have registered. toggle_light_dark uses it to select the other default theme.
Setting a custom theme
set_theme(theme, cx) registers and activates a theme in one step — use it when the theme was built with Theme::builder and has not been registered yet.
1herogpui::theme::use_theme("dark", cx);
2// or
3herogpui::theme::set_theme(my_custom_dark_theme, cx);Reading the active appearance
ActiveTheme exposes cx.is_dark_theme() for a boolean. The provider also keeps the active id if you need the name. Both update when a switch lands.
1if cx.is_dark_theme() {
2 // your own dark-mode branch
3}
4
5// or ask the provider for the active id: "light", "dark", or a custom one
6let id = herogpui::theme::ThemeProvider::get(cx).active_id().clone();Reduced motion
The same provider holds the app-level reduced-motion preference, because GPUI does not surface the OS prefers-reduced-motion setting. Seed it at startup with HEROGPUI_REDUCE_MOTION=1, or override it at any time with theme::set_reduce_motion(bool, cx) / toggle_reduce_motion(cx) — the app-level equivalent of enabling a reduced-motion setting. Every animated component honours it through cx.reduce_motion() without caller opt-in.