From 21da001bf54d29d7269dd2231df4f3aec2245320 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Sun, 10 May 2026 00:57:59 -0400 Subject: [PATCH] Make topbar moon button actually toggle theme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- crates/ely_app/src/shell/chrome/topbar.rs | 18 +++++++++++++++--- crates/ely_app/src/shell/settings_actions.rs | 17 +++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/crates/ely_app/src/shell/chrome/topbar.rs b/crates/ely_app/src/shell/chrome/topbar.rs index d9af1e7..ef5d6d2 100644 --- a/crates/ely_app/src/shell/chrome/topbar.rs +++ b/crates/ely_app/src/shell/chrome/topbar.rs @@ -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 { vec![ BoxShadow { diff --git a/crates/ely_app/src/shell/settings_actions.rs b/crates/ely_app/src/shell/settings_actions.rs index 842cc70..eb61940 100644 --- a/crates/ely_app/src/shell/settings_actions.rs +++ b/crates/ely_app/src/shell/settings_actions.rs @@ -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) { + 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) { if let ShellState::Ready(core) = &mut self.state { let next = !core.appearance().reduce_motion();