diff --git a/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/ThemeScripts.razor b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/ThemeScripts.razor new file mode 100644 index 0000000..a73a0d5 --- /dev/null +++ b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/Components/ThemeScripts.razor @@ -0,0 +1,4 @@ +@namespace ZB.MOM.WW.Theme +@* Components/ThemeScripts.razor — drop before . Emits the kit's nav-state + enhancer that persists NavRailSection open/closed state in localStorage. *@ + diff --git a/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/wwwroot/js/nav-state.js b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/wwwroot/js/nav-state.js new file mode 100644 index 0000000..4715c17 --- /dev/null +++ b/ZB.MOM.WW.Theme/src/ZB.MOM.WW.Theme/wwwroot/js/nav-state.js @@ -0,0 +1,22 @@ +// ZB.MOM.WW.Theme nav-state.js — persists
open/closed +// state in localStorage so NavRailSection expand state survives navigation and +// reloads. Pure client-side; works with static Blazor SSR. Keyed per section. +(function () { + var PREFIX = "zbnav:"; + function apply() { + document.querySelectorAll("details.rail-section[data-nav-key]").forEach(function (el) { + var key = PREFIX + el.getAttribute("data-nav-key"); + var saved = null; + try { saved = window.localStorage.getItem(key); } catch (e) { return; } + if (saved === "1") el.open = true; + else if (saved === "0") el.open = false; + el.addEventListener("toggle", function () { + try { window.localStorage.setItem(key, el.open ? "1" : "0"); } catch (e) { /* ignore */ } + }); + }); + } + if (document.readyState === "loading") + document.addEventListener("DOMContentLoaded", apply); + else + apply(); +})(); diff --git a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/StaticAssetsTests.cs b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/StaticAssetsTests.cs index 73b3da2..86e8d43 100644 --- a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/StaticAssetsTests.cs +++ b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/StaticAssetsTests.cs @@ -35,6 +35,10 @@ public class StaticAssetsTests public void Fonts_are_vendored(string file) => Assert.True(File.Exists(Path.Combine(Wwwroot, "fonts", file))); + [Fact] + public void NavStateScript_ships() => + Assert.True(File.Exists(Path.Combine(Wwwroot, "js", "nav-state.js"))); + // Theme-002: .chip-idle pairs the idle background with the matching --idle // foreground token (per DESIGN-TOKENS.md), not --ink-soft. [Fact] diff --git a/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/ThemeScriptsTests.cs b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/ThemeScriptsTests.cs new file mode 100644 index 0000000..4478cb3 --- /dev/null +++ b/ZB.MOM.WW.Theme/tests/ZB.MOM.WW.Theme.Tests/ThemeScriptsTests.cs @@ -0,0 +1,13 @@ +namespace ZB.MOM.WW.Theme.Tests; + +public class ThemeScriptsTests : TestContext +{ + [Fact] + public void ThemeScripts_emits_nav_state_script_tag() + { + var cut = RenderComponent(); + var script = cut.Find("script"); + Assert.Equal("_content/ZB.MOM.WW.Theme/js/nav-state.js", script.GetAttribute("src")); + Assert.True(script.HasAttribute("defer")); + } +}