Mercurial
diff design_system/src/components/story.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 | 2b6e732087ff |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/design_system/src/components/story.js Tue Aug 04 09:14:57 2026 -0700 @@ -0,0 +1,57 @@ +function normalizeSource(source) { + const lines = source.replace(/^\n|\n\s*$/g, "").split("\n"); + const indentation = lines + .filter(line => line.trim()) + .map(line => line.match(/^\s*/)[0].length); + const minimum = indentation.length + ? Math.min(...indentation) + : 0; + return lines.map(line => line.slice(minimum)).join("\n"); +} + +export class ZenStory extends HTMLElement { + connectedCallback() { + if (this.dataset.ready === "true") return; + const template = this.querySelector(":scope > template"); + if (!template) return; + this.dataset.ready = "true"; + + const heading = document.createElement("header"); + const title = document.createElement("h3"); + title.textContent = this.getAttribute("name") || "Example"; + heading.append(title); + + const copy = document.createElement("button"); + copy.type = "button"; + copy.textContent = "Copy HTML"; + copy.addEventListener("click", async () => { + try { + await navigator.clipboard.writeText( + normalizeSource(template.innerHTML), + ); + copy.textContent = "Copied"; + } catch { + copy.textContent = "Copy unavailable"; + } + setTimeout(() => { + copy.textContent = "Copy HTML"; + }, 1200); + }); + heading.append(copy); + + const canvas = document.createElement("div"); + canvas.className = "story-canvas"; + canvas.append(template.content.cloneNode(true)); + + const source = document.createElement("pre"); + const code = document.createElement("code"); + code.textContent = normalizeSource(template.innerHTML); + source.append(code); + + this.prepend(heading, canvas, source); + } +} + +if (!customElements.get("zen-story")) { + customElements.define("zen-story", ZenStory); +}