From 9731b68c1c9c0c1fad132754c4d89a32d229061c Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 9 Nov 2025 13:01:53 +0000 Subject: [PATCH] feat: Implement light/dark theme switching and responsive full-height layout - Add Theme property to SystemConfiguration entity with default "Light" value - Add theme selector dropdown to Settings page (Light/Dark mode) - Update MainLayout with theme loading and JavaScript interop for applying themes - Redesign navigation with large icons (40px) and text labels below - Add equal spacing throughout navigation bar height using space-evenly - Implement responsive full-height dashboard layout using flexbox - Update diagram area to fill available vertical space with flex: 1 - Convert all hardcoded colors to CSS custom properties for theme support - Add responsive mobile optimizations for different orientations Theme changes persist across page reloads via settings API. --- .../Entities/SystemConfiguration.cs | 1 + src/Frontend/VanDaemon.Web/Pages/Index.razor | 70 +++++++++++++---- .../VanDaemon.Web/Pages/Settings.razor | 10 +++ .../VanDaemon.Web/Shared/MainLayout.razor | 77 +++++++++++++------ 4 files changed, 120 insertions(+), 38 deletions(-) diff --git a/src/Backend/VanDaemon.Core/Entities/SystemConfiguration.cs b/src/Backend/VanDaemon.Core/Entities/SystemConfiguration.cs index 397fafd..31bec2c 100644 --- a/src/Backend/VanDaemon.Core/Entities/SystemConfiguration.cs +++ b/src/Backend/VanDaemon.Core/Entities/SystemConfiguration.cs @@ -19,6 +19,7 @@ public class SystemConfiguration public string VanModel { get; set; } = "Mercedes Sprinter LWB"; public string VanDiagramPath { get; set; } = "/diagrams/sprinter-lwb.svg"; public ToolbarPosition ToolbarPosition { get; set; } = ToolbarPosition.Left; + public string Theme { get; set; } = "Light"; public AlertSettings AlertSettings { get; set; } = new(); public Dictionary PluginConfigurations { get; set; } = new(); public DateTime LastUpdated { get; set; } diff --git a/src/Frontend/VanDaemon.Web/Pages/Index.razor b/src/Frontend/VanDaemon.Web/Pages/Index.razor index eeb26fc..5881807 100644 --- a/src/Frontend/VanDaemon.Web/Pages/Index.razor +++ b/src/Frontend/VanDaemon.Web/Pages/Index.razor @@ -8,6 +8,35 @@ Dashboard - VanDaemon - -
+
+
+ ToggledTitle="Exit Edit Mode" + Size="Size.Large" + Color="Color.Primary" />
-
-
+
@if (!string.IsNullOrEmpty(backgroundImage)) { Van Diagram } else { -
- +
+ No background image configured Go to Settings to upload a van diagram
@@ -74,7 +113,7 @@ @if (overlay.Type == OverlayType.Tank) { -
+
@overlay.Value.ToString("F1")%
@@ -83,7 +122,7 @@ else if (overlay.Type == OverlayType.Control) { -
+
- -
+ - +
@code { private List? tanks; diff --git a/src/Frontend/VanDaemon.Web/Pages/Settings.razor b/src/Frontend/VanDaemon.Web/Pages/Settings.razor index 700fa74..974533d 100644 --- a/src/Frontend/VanDaemon.Web/Pages/Settings.razor +++ b/src/Frontend/VanDaemon.Web/Pages/Settings.razor @@ -80,6 +80,15 @@ else Bottom Bar (Tablet/Desktop) + + Light Mode + Dark Mode + + Upload Custom Van Diagram @@ -34,54 +35,58 @@ box-shadow: var(--mud-elevation-2); display: flex; flex-direction: column; + justify-content: space-evenly; } .toolbar-left .nav-area, .toolbar-right .nav-area { - width: 280px; - padding: 16px; + width: 120px; + padding: 24px 8px; } .toolbar-bottom .nav-area { width: 100%; flex-direction: row; justify-content: space-around; - padding: 12px 16px; + padding: 16px; height: auto; } .main-area { grid-area: main; overflow: auto; - padding: 16px; + padding: 0; + height: 100%; } .nav-item { display: flex; + flex-direction: column; align-items: center; - gap: 12px; - padding: 16px; + justify-content: center; + gap: 8px; + padding: 20px 12px; margin: 4px 0; - border-radius: 8px; + border-radius: 12px; cursor: pointer; - transition: background-color 0.2s; + transition: background-color 0.2s, transform 0.1s; text-decoration: none; color: inherit; - min-height: 56px; + min-height: 90px; } .toolbar-bottom .nav-item { flex-direction: column; - padding: 12px 8px; - margin: 0; - gap: 4px; - min-width: 80px; - text-align: center; - min-height: 72px; + padding: 16px 12px; + margin: 0 4px; + gap: 8px; + min-width: 90px; + min-height: 80px; } .nav-item:hover { background-color: var(--mud-palette-action-default-hover); + transform: translateY(-2px); } .nav-item.active { @@ -90,14 +95,22 @@ } .nav-item-icon { - font-size: 28px; - width: 28px; - height: 28px; + font-size: 40px !important; + width: 40px; + height: 40px; } .nav-item-text { - font-size: 16px; + font-size: 13px; font-weight: 500; + text-align: center; + line-height: 1.2; + } + + .toolbar-bottom .nav-item-icon { + font-size: 36px !important; + width: 36px; + height: 36px; } .toolbar-bottom .nav-item-text { @@ -240,17 +253,18 @@ else private bool isLoading = true; private string toolbarPosition = "toolbar-left"; private string currentPath = "/"; + private string currentTheme = "Light"; protected override async Task OnInitializedAsync() { currentPath = new Uri(NavigationManager.Uri).AbsolutePath; NavigationManager.LocationChanged += OnLocationChanged; - await LoadToolbarPosition(); + await LoadSettings(); isLoading = false; } - private async Task LoadToolbarPosition() + private async Task LoadSettings() { try { @@ -264,12 +278,30 @@ else "Bottom" => "toolbar-bottom", _ => "toolbar-left" }; + + currentTheme = config.Theme ?? "Light"; + await ApplyTheme(currentTheme); } } catch (Exception ex) { - Console.WriteLine($"Error loading toolbar position: {ex.Message}"); + Console.WriteLine($"Error loading settings: {ex.Message}"); toolbarPosition = "toolbar-left"; + currentTheme = "Light"; + } + } + + private async Task ApplyTheme(string theme) + { + try + { + var isDark = theme == "Dark"; + await JSRuntime.InvokeVoidAsync("eval", + $"document.documentElement.setAttribute('data-theme', '{(isDark ? "dark" : "light")}')"); + } + catch (Exception ex) + { + Console.WriteLine($"Error applying theme: {ex.Message}"); } } @@ -305,6 +337,7 @@ else public string VanModel { get; set; } = string.Empty; public string VanDiagramPath { get; set; } = string.Empty; public string ToolbarPosition { get; set; } = "Left"; + public string Theme { get; set; } = "Light"; public AlertSettingsDto AlertSettings { get; set; } = new(); public DateTime LastUpdated { get; set; } }