Make topbar moon button actually toggle theme

The Moon icon previously navigated to ely://settings/appearance,
which is misleading for a button visually framed as a one-tap theme
control. Add cycle_theme_mode (System → Light → Dark → System) and
swap the icon between Sun and Moon to mirror the active state.
This commit is contained in:
2026-05-10 00:57:59 -04:00
parent f2799e89c9
commit 21da001bf5
2 changed files with 32 additions and 3 deletions
+15 -3
View File
@@ -1,6 +1,6 @@
use ely_browser_core::BrowserSnapshot;
use ely_design_system::{colors, spacing};
use ely_domain::BrowserTab;
use ely_domain::{BrowserTab, ThemeMode};
use gpui::{
AnyElement, BoxShadow, Context, FontWeight, InteractiveElement, IntoElement, ParentElement,
SharedString, StatefulInteractiveElement, Styled, div, hsla, point,
@@ -47,9 +47,9 @@ pub(crate) fn render_topbar(
))
.child(render_topbar_action(
"toggle-theme",
IconName::Moon,
theme_mode_icon(snapshot.appearance.theme_mode()),
cx,
|shell, window, cx| shell.open_internal_tab("ely://settings/appearance", window, cx),
|shell, _window, cx| shell.cycle_theme_mode(cx),
))
.child(render_topbar_action(
"open-menu",
@@ -249,6 +249,18 @@ where
const OMNIBAR_BG: u32 = 0xffffff8c;
const CHIP_HOVER_BG: u32 = 0xffffffd9;
/// Topbar quick-toggle icon for the current theme mode. The button
/// cycles System → Light → Dark → System, and the icon previews the
/// state the user is in: sun for light, moon for dark. System falls
/// back to moon since the bundled icon set has no combined sun-moon
/// glyph and the OS-driven mode visually leans neutral.
fn theme_mode_icon(mode: ThemeMode) -> IconName {
match mode {
ThemeMode::Light => IconName::Sun,
ThemeMode::System | ThemeMode::Dark => IconName::Moon,
}
}
fn soft_shadow() -> Vec<BoxShadow> {
vec![
BoxShadow {
@@ -72,6 +72,23 @@ impl ElyShell {
}
}
/// Cycle the theme mode for the topbar's quick-toggle button:
/// System → Light → Dark → System. Mirrors the segmented control
/// in the appearance settings page so the topbar toggle reaches
/// every state without spawning a settings page.
pub(super) fn cycle_theme_mode(&mut self, cx: &mut Context<Self>) {
let ShellState::Ready(core) = &mut self.state else {
return;
};
let next = match core.appearance().theme_mode() {
ThemeMode::System => ThemeMode::Light,
ThemeMode::Light => ThemeMode::Dark,
ThemeMode::Dark => ThemeMode::System,
};
core.set_theme_mode(next);
cx.notify();
}
pub(super) fn toggle_reduce_motion(&mut self, cx: &mut Context<Self>) {
if let ShellState::Ready(core) = &mut self.state {
let next = !core.appearance().reduce_motion();