comparison 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
comparison
equal deleted inserted replaced
250:745fd127b2a1 251:117c4d53c9a4
1 function normalizeSource(source) {
2 const lines = source.replace(/^\n|\n\s*$/g, "").split("\n");
3 const indentation = lines
4 .filter(line => line.trim())
5 .map(line => line.match(/^\s*/)[0].length);
6 const minimum = indentation.length
7 ? Math.min(...indentation)
8 : 0;
9 return lines.map(line => line.slice(minimum)).join("\n");
10 }
11
12 export class ZenStory extends HTMLElement {
13 connectedCallback() {
14 if (this.dataset.ready === "true") return;
15 const template = this.querySelector(":scope > template");
16 if (!template) return;
17 this.dataset.ready = "true";
18
19 const heading = document.createElement("header");
20 const title = document.createElement("h3");
21 title.textContent = this.getAttribute("name") || "Example";
22 heading.append(title);
23
24 const copy = document.createElement("button");
25 copy.type = "button";
26 copy.textContent = "Copy HTML";
27 copy.addEventListener("click", async () => {
28 try {
29 await navigator.clipboard.writeText(
30 normalizeSource(template.innerHTML),
31 );
32 copy.textContent = "Copied";
33 } catch {
34 copy.textContent = "Copy unavailable";
35 }
36 setTimeout(() => {
37 copy.textContent = "Copy HTML";
38 }, 1200);
39 });
40 heading.append(copy);
41
42 const canvas = document.createElement("div");
43 canvas.className = "story-canvas";
44 canvas.append(template.content.cloneNode(true));
45
46 const source = document.createElement("pre");
47 const code = document.createElement("code");
48 code.textContent = normalizeSource(template.innerHTML);
49 source.append(code);
50
51 this.prepend(heading, canvas, source);
52 }
53 }
54
55 if (!customElements.get("zen-story")) {
56 customElements.define("zen-story", ZenStory);
57 }