Mercurial
diff design_system/src/storybook.js @ 251:117c4d53c9a4
[ui] Add HTML-first Web Component system
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Tue, 04 Aug 2026 09:14:57 -0700 |
| parents | |
| children | 7a7581f040e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/design_system/src/storybook.js Tue Aug 04 09:14:57 2026 -0700 @@ -0,0 +1,84 @@ +import "./components/index.js"; + +const pages = new Map([ + ["/", "overview"], + ["/components", "overview"], + ["/tokens", "tokens"], + ["/components/button", "button"], + ["/components/card", "card"], + ["/components/alert", "alert"], + ["/components/field", "field"], + ["/components/stack", "stack"], +]); + +function showPage(pathname) { + const pageName = pages.get(pathname) || "overview"; + for (const page of document.querySelectorAll("[data-catalog-page]")) { + page.hidden = page.dataset.catalogPage !== pageName; + } + for (const link of document.querySelectorAll( + ".catalog-sidebar [data-catalog-link]", + )) { + const active = new URL(link.href).pathname === pathname; + if (active) link.setAttribute("aria-current", "page"); + else link.removeAttribute("aria-current"); + } + const heading = document.querySelector( + `[data-catalog-page="${pageName}"] h1`, + ); + if (heading) document.title = `${heading.textContent} ยท Zenbu UI`; +} + +window.addEventListener("DOMContentLoaded", () => { + const root = document.documentElement; + const systemTheme = matchMedia("(prefers-color-scheme: dark)"); + const storedTheme = localStorage.getItem("zen-theme"); + if (storedTheme) root.dataset.zenTheme = storedTheme; + + const themeToggle = document.querySelector("#themeToggle"); + const isDark = () => { + if (root.dataset.zenTheme) { + return root.dataset.zenTheme === "dark"; + } + return systemTheme.matches; + }; + const updateThemeButton = () => { + const dark = isDark(); + themeToggle?.setAttribute("aria-pressed", String(dark)); + if (themeToggle) { + themeToggle.textContent = dark + ? "Use light theme" + : "Use dark theme"; + } + }; + updateThemeButton(); + themeToggle?.addEventListener("click", () => { + const next = isDark() ? "light" : "dark"; + root.dataset.zenTheme = next; + localStorage.setItem("zen-theme", next); + updateThemeButton(); + }); + systemTheme.addEventListener("change", () => { + if (!root.dataset.zenTheme) updateThemeButton(); + }); + + document.addEventListener("click", event => { + const link = event.target.closest("a[data-catalog-link]"); + if (!link || + link.origin !== location.origin || + event.defaultPrevented || + event.button !== 0 || + event.metaKey || + event.ctrlKey || + event.shiftKey || + event.altKey || + link.hasAttribute("download") || + link.target) return; + event.preventDefault(); + history.pushState({}, "", link.href); + showPage(location.pathname); + document.querySelector("#catalogMain")?.focus(); + }); + window.addEventListener("popstate", () => showPage(location.pathname)); + showPage(location.pathname); +});