From 0bc1941aee415a3c593603ef5c272fbf4302683d Mon Sep 17 00:00:00 2001 From: nolt Date: Fri, 29 May 2026 11:09:17 +0000 Subject: [PATCH 1/5] add dark mode toggle to admin panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cookie-persisted dark/light theme toggle in the panel header, mirroring the CultureSelector pattern. ThemeController writes an OpenMU.Theme cookie; App.razor reads it on SSR to set ; theme.css and CSS-isolation files drive the colors via CSS variables. ThemeSelector hydrates from the live DOM via a small JS module after the interactive Blazor circuit takes over (cascading HttpContext is null in interactive renders). theme.css is shipped as a plain static asset rather than going through the SCSS pipeline because the Docker build skips Sass with ci=true. --- src/Web/AdminPanel/Components/App.razor | 11 +- .../Layout/ConfigurationSearch.razor.css | 4 +- .../Components/Layout/CreationPanel.razor.css | 13 +- .../Components/Layout/MainLayout.razor | 18 +- .../Components/Layout/MainLayout.razor.css | 7 +- src/Web/AdminPanel/_Imports.razor | 1 + .../Shared/Components/Form/AutoForm.razor.css | 11 +- src/Web/Shared/Components/ThemeSelector.razor | 20 ++ .../Shared/Components/ThemeSelector.razor.cs | 110 +++++++ .../Shared/Components/ThemeSelector.razor.css | 22 ++ src/Web/Shared/Exports.cs | 1 + .../Shared/Properties/Resources.Designer.cs | 18 ++ src/Web/Shared/Properties/Resources.resx | 9 + src/Web/Shared/Services/ThemeController.cs | 56 ++++ src/Web/Shared/wwwroot/css/theme.css | 273 ++++++++++++++++++ src/Web/Shared/wwwroot/themeSelector.js | 17 ++ 16 files changed, 571 insertions(+), 20 deletions(-) create mode 100644 src/Web/Shared/Components/ThemeSelector.razor create mode 100644 src/Web/Shared/Components/ThemeSelector.razor.cs create mode 100644 src/Web/Shared/Components/ThemeSelector.razor.css create mode 100644 src/Web/Shared/Services/ThemeController.cs create mode 100644 src/Web/Shared/wwwroot/css/theme.css create mode 100644 src/Web/Shared/wwwroot/themeSelector.js diff --git a/src/Web/AdminPanel/Components/App.razor b/src/Web/AdminPanel/Components/App.razor index 55f285156..885e14167 100644 --- a/src/Web/AdminPanel/Components/App.razor +++ b/src/Web/AdminPanel/Components/App.razor @@ -1,7 +1,16 @@ @using MUnique.OpenMU.Web.AdminPanel.Components.Layout +@using MUnique.OpenMU.Web.Shared.Services + +@code { + [CascadingParameter] + public HttpContext? HttpContext { get; set; } + + private string CurrentTheme => + ThemeController.NormalizeTheme(this.HttpContext?.Request.Cookies[ThemeController.CookieName]); +} - + diff --git a/src/Web/AdminPanel/Components/Layout/ConfigurationSearch.razor.css b/src/Web/AdminPanel/Components/Layout/ConfigurationSearch.razor.css index 4330a2f3e..0f9834f6f 100644 --- a/src/Web/AdminPanel/Components/Layout/ConfigurationSearch.razor.css +++ b/src/Web/AdminPanel/Components/Layout/ConfigurationSearch.razor.css @@ -36,7 +36,7 @@ .configuration-search__result-path { font-size: 0.78rem; - color: #5f6368; + color: var(--omu-text-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; @@ -45,7 +45,7 @@ .configuration-search__result:hover .configuration-search__result-path, .configuration-search__result:focus .configuration-search__result-path { - color: rgba(0, 0, 0, 0.7); + color: var(--omu-text); } @media (max-width: 640.98px) { diff --git a/src/Web/AdminPanel/Components/Layout/CreationPanel.razor.css b/src/Web/AdminPanel/Components/Layout/CreationPanel.razor.css index 65f4099ac..f1505d24c 100644 --- a/src/Web/AdminPanel/Components/Layout/CreationPanel.razor.css +++ b/src/Web/AdminPanel/Components/Layout/CreationPanel.razor.css @@ -6,8 +6,9 @@ flex-shrink: 0; display: flex; flex-direction: row; - background-color: #fff; - border-left: 1px solid #d6d5d5; + background-color: var(--omu-surface-2); + color: var(--omu-text); + border-left: 1px solid var(--omu-border); box-shadow: -2px 0 5px rgba(0, 0, 0, 0.08); overflow: hidden; z-index: 2; @@ -22,14 +23,14 @@ width: 1.75rem; padding: 0; border: none; - border-right: 1px solid #d6d5d5; - background-color: #f7f7f7; + border-right: 1px solid var(--omu-border); + background-color: var(--omu-surface-muted); cursor: pointer; - color: #333; + color: var(--omu-text); } .collapse-toggle:hover { - background-color: #e9e9e9; + background-color: var(--omu-surface-hover); } .creation-panel-body { diff --git a/src/Web/AdminPanel/Components/Layout/MainLayout.razor b/src/Web/AdminPanel/Components/Layout/MainLayout.razor index 0d915160d..6001649ef 100644 --- a/src/Web/AdminPanel/Components/Layout/MainLayout.razor +++ b/src/Web/AdminPanel/Components/Layout/MainLayout.razor @@ -1,7 +1,18 @@ @using MUnique.OpenMU.Web.AdminPanel.Properties +@using MUnique.OpenMU.Web.Shared.Services @inherits LayoutComponentBase +@code { + [CascadingParameter] + public HttpContext? HttpContext { get; set; } + + private bool IsDarkTheme => string.Equals( + this.HttpContext?.Request.Cookies[ThemeController.CookieName], + "dark", + StringComparison.OrdinalIgnoreCase); +} +
-