comparison design_system/src/components/link.js @ 258:60a876c4587a

[ui] Add semantic primitive ownership Build a layered Zenbu token and sizing system, make authored controls use native-underneath primitives, migrate mrjunejune without imposing visual surfaces, and document/enforce HTML ownership in the catalog and wiki. Co-authored-by: Copilot <[email protected]>
author MrJuneJune <me@mrjunejune.com>
date Wed, 05 Aug 2026 05:25:40 -0700
parents
children
comparison
equal deleted inserted replaced
257:609d3c6aff4e 258:60a876c4587a
1 /**
2 * Adds an optional reusable effect to one direct native link.
3 *
4 * @extends {HTMLElement}
5 */
6 export class ZenLink extends HTMLElement {
7 static get observedAttributes() {
8 return ["effect"];
9 }
10
11 connectedCallback() {
12 this._observer ||= new MutationObserver(() => this.sync());
13 this._observer.observe(this, { childList: true });
14 this.sync();
15 }
16
17 disconnectedCallback() {
18 this._observer?.disconnect();
19 this.removeGeneratedDecoration();
20 }
21
22 attributeChangedCallback() {
23 if (this.isConnected) this.sync();
24 }
25
26 removeGeneratedDecoration() {
27 this.querySelector(
28 ':scope > a > zen-icon[data-zen-link-decoration][data-zen-generated="true"]',
29 )?.remove();
30 }
31
32 sync() {
33 const link = this.querySelector(":scope > a");
34 if (!link || this.getAttribute("effect") !== "paw") {
35 this.removeGeneratedDecoration();
36 return;
37 }
38 let decoration = link.querySelector(
39 ":scope > zen-icon[data-zen-link-decoration]",
40 );
41 if (!decoration) {
42 decoration = document.createElement("zen-icon");
43 decoration.dataset.zenLinkDecoration = "";
44 decoration.dataset.zenGenerated = "true";
45 decoration.setAttribute("name", "paw");
46 link.prepend(decoration);
47 }
48 }
49 }
50
51 if (!customElements.get("zen-link")) {
52 customElements.define("zen-link", ZenLink);
53 }