diff --git a/docs/tables_frontend_overhaul_implementation_plan.md b/docs/tables_frontend_overhaul_implementation_plan.md index b454327..09d7931 100644 --- a/docs/tables_frontend_overhaul_implementation_plan.md +++ b/docs/tables_frontend_overhaul_implementation_plan.md @@ -49,6 +49,7 @@ It is intentionally implementation-focused: | 2026-03-21 | Post-P1 fix 1 | Completed | Closed the 768px-1023px navigation gap by adding a shell hamburger menu and drawer so primary navigation never disappears at tablet widths. | | 2026-03-21 | Post-P1 fix 2 | Completed | Replaced the most visible light-only surface and control colors with theme-aware tokens so switching between `Light`, `Dark`, and `System` produces a clear visual change. | | 2026-03-21 | Post-P1 fix 3 | Completed | Restored layout-level shell interactivity by rendering routed content in `InteractiveServer` mode, which re-enabled shell event handlers such as the hamburger menu and theme selector. | +| 2026-03-21 | Post-P1 fix 4 | Completed | Added early theme bootstrapping in `App.razor` and `theme.js` so the stored mode is applied before hydration and remains visible after refresh. | ### Lessons Learned @@ -67,6 +68,7 @@ It is intentionally implementation-focused: - Responsive shell design needs an explicit tablet state, not just desktop and phone states. The original breakpoints left a navigation dead zone between the top nav and bottom nav layouts. - Theme infrastructure is not enough on its own. Any surface that keeps hardcoded light values will make the theme switch feel broken even when the selector logic is correct. - In Blazor Web Apps, page-level render modes do not automatically make layout-level controls interactive in the way this shell expects. The routed shell itself needs an interactive render boundary. +- Persisted theme state should be applied before Blazor hydrates, not only after layout initialization. Otherwise refresh can look broken even when storage writes succeed. ## Target Outcomes diff --git a/src/RolemasterDb.App/Components/App.razor b/src/RolemasterDb.App/Components/App.razor index 1933265..5554142 100644 --- a/src/RolemasterDb.App/Components/App.razor +++ b/src/RolemasterDb.App/Components/App.razor @@ -12,6 +12,8 @@ + + @@ -20,7 +22,6 @@ - diff --git a/src/RolemasterDb.App/wwwroot/theme.js b/src/RolemasterDb.App/wwwroot/theme.js index 484ca30..0425ffe 100644 --- a/src/RolemasterDb.App/wwwroot/theme.js +++ b/src/RolemasterDb.App/wwwroot/theme.js @@ -1,5 +1,23 @@ window.rolemasterTheme = { + storageKey: "rolemaster.theme.mode", + apply(mode) { document.documentElement.dataset.theme = mode || "system"; + }, + + init(storageKey) { + if (storageKey) { + this.storageKey = storageKey; + } + + let mode = "system"; + + try { + mode = localStorage.getItem(this.storageKey) || "system"; + } catch { + mode = "system"; + } + + this.apply(mode); } };