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);
+});