Mercurial
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 250:745fd127b2a1 | 251:117c4d53c9a4 |
|---|---|
| 1 import "./components/index.js"; | |
| 2 | |
| 3 const pages = new Map([ | |
| 4 ["/", "overview"], | |
| 5 ["/components", "overview"], | |
| 6 ["/tokens", "tokens"], | |
| 7 ["/components/button", "button"], | |
| 8 ["/components/card", "card"], | |
| 9 ["/components/alert", "alert"], | |
| 10 ["/components/field", "field"], | |
| 11 ["/components/stack", "stack"], | |
| 12 ]); | |
| 13 | |
| 14 function showPage(pathname) { | |
| 15 const pageName = pages.get(pathname) || "overview"; | |
| 16 for (const page of document.querySelectorAll("[data-catalog-page]")) { | |
| 17 page.hidden = page.dataset.catalogPage !== pageName; | |
| 18 } | |
| 19 for (const link of document.querySelectorAll( | |
| 20 ".catalog-sidebar [data-catalog-link]", | |
| 21 )) { | |
| 22 const active = new URL(link.href).pathname === pathname; | |
| 23 if (active) link.setAttribute("aria-current", "page"); | |
| 24 else link.removeAttribute("aria-current"); | |
| 25 } | |
| 26 const heading = document.querySelector( | |
| 27 `[data-catalog-page="${pageName}"] h1`, | |
| 28 ); | |
| 29 if (heading) document.title = `${heading.textContent} ยท Zenbu UI`; | |
| 30 } | |
| 31 | |
| 32 window.addEventListener("DOMContentLoaded", () => { | |
| 33 const root = document.documentElement; | |
| 34 const systemTheme = matchMedia("(prefers-color-scheme: dark)"); | |
| 35 const storedTheme = localStorage.getItem("zen-theme"); | |
| 36 if (storedTheme) root.dataset.zenTheme = storedTheme; | |
| 37 | |
| 38 const themeToggle = document.querySelector("#themeToggle"); | |
| 39 const isDark = () => { | |
| 40 if (root.dataset.zenTheme) { | |
| 41 return root.dataset.zenTheme === "dark"; | |
| 42 } | |
| 43 return systemTheme.matches; | |
| 44 }; | |
| 45 const updateThemeButton = () => { | |
| 46 const dark = isDark(); | |
| 47 themeToggle?.setAttribute("aria-pressed", String(dark)); | |
| 48 if (themeToggle) { | |
| 49 themeToggle.textContent = dark | |
| 50 ? "Use light theme" | |
| 51 : "Use dark theme"; | |
| 52 } | |
| 53 }; | |
| 54 updateThemeButton(); | |
| 55 themeToggle?.addEventListener("click", () => { | |
| 56 const next = isDark() ? "light" : "dark"; | |
| 57 root.dataset.zenTheme = next; | |
| 58 localStorage.setItem("zen-theme", next); | |
| 59 updateThemeButton(); | |
| 60 }); | |
| 61 systemTheme.addEventListener("change", () => { | |
| 62 if (!root.dataset.zenTheme) updateThemeButton(); | |
| 63 }); | |
| 64 | |
| 65 document.addEventListener("click", event => { | |
| 66 const link = event.target.closest("a[data-catalog-link]"); | |
| 67 if (!link || | |
| 68 link.origin !== location.origin || | |
| 69 event.defaultPrevented || | |
| 70 event.button !== 0 || | |
| 71 event.metaKey || | |
| 72 event.ctrlKey || | |
| 73 event.shiftKey || | |
| 74 event.altKey || | |
| 75 link.hasAttribute("download") || | |
| 76 link.target) return; | |
| 77 event.preventDefault(); | |
| 78 history.pushState({}, "", link.href); | |
| 79 showPage(location.pathname); | |
| 80 document.querySelector("#catalogMain")?.focus(); | |
| 81 }); | |
| 82 window.addEventListener("popstate", () => showPage(location.pathname)); | |
| 83 showPage(location.pathname); | |
| 84 }); |