From d49af5d785019b5a76c8a3624cb49a722d3f9499 Mon Sep 17 00:00:00 2001 From: "Valentin V. Bartenev" Date: Sat, 9 May 2026 17:40:51 +0300 Subject: [PATCH] Web: bring theme toggle to the login page for consistent UX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The app and stats pages already use an explicit data-theme attribute approach — reading the saved "repeater-theme" key from localStorage and falling back to the OS preference — with a ☾/☀ toggle button in the UI. The login page was the only page still relying solely on the CSS @media (prefers-color-scheme) query with no manual override. This commit mirrors the same pattern on the login page so the theme switcher works consistently across all pages: - Add --surface2 CSS variable to both light and dark theme blocks - Replace @media (prefers-color-scheme: dark) with :root[data-theme="dark"] - Add a theme toggle button (☾/☀) in the login card header - Add getPreferredTheme(), applyTheme(), and toggleTheme() helpers, identical in behaviour to those already present on the app page --- src/helpers/web/WebPanelServer.cpp | 49 ++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 12 deletions(-) diff --git a/src/helpers/web/WebPanelServer.cpp b/src/helpers/web/WebPanelServer.cpp index 807f8b01..2621438d 100644 --- a/src/helpers/web/WebPanelServer.cpp +++ b/src/helpers/web/WebPanelServer.cpp @@ -225,18 +225,18 @@ const char kWebPanelLoginHtml[] PROGMEM = R"HTML( --text-muted:#4b5563; --border:rgba(0,0,0,.08); --surface:#ffffff; + --surface2:#f0f3f7; } - @media (prefers-color-scheme: dark) { - :root { - color-scheme: dark; - --accent:#36a167; - --accent-hover:#49c27d; - --background:#222222; - --text:#e6eaf0; - --text-muted:#9aa4b2; - --border:rgba(255,255,255,.08); - --surface:#303030; - } + :root[data-theme="dark"] { + color-scheme: dark; + --accent:#36a167; + --accent-hover:#49c27d; + --background:#222222; + --text:#e6eaf0; + --text-muted:#9aa4b2; + --border:rgba(255,255,255,.08); + --surface:#303030; + --surface2:#2a2a2a; } html { min-height:100%; background:linear-gradient(180deg,var(--background),var(--surface)); background-repeat:no-repeat; background-attachment:fixed; } body { min-height:100vh; margin:0; display:grid; place-items:center; background:transparent; color:var(--text); font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono",monospace; } @@ -249,12 +249,17 @@ const char kWebPanelLoginHtml[] PROGMEM = R"HTML( button { border:none; background:var(--accent); color:#fff; cursor:pointer; font-weight:700; } button:hover { background:var(--accent-hover); } #status { min-height:1.4em; margin-top:12px; color:#c94a4a; white-space:pre-wrap; } + .themebtn { background:var(--surface2,var(--background)); color:var(--text); border:1px solid var(--border); } + .themebtn:hover { background:var(--surface); }
-

Repeater Config

+
+

Repeater Config

+ +
Use the repeater admin password to unlock the panel.

@@ -262,6 +267,26 @@ const char kWebPanelLoginHtml[] PROGMEM = R"HTML(