@profpowell/vb-design-system 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/vb-design-system.css +5 -5
- package/dist/vb-design-system.js +37 -35
- package/dist/vb-design-system.min.css +1 -1
- package/dist/vb-design-system.min.js +28 -28
- package/package.json +6 -6
- package/src/lib/vb-element.js +15 -1
- package/src/web-components/breakpoint-specimen/styles.css +2 -2
- package/src/web-components/font-pairer/logic.js +16 -16
- package/src/web-components/gradient-builder/logic.js +1 -1
- package/src/web-components/motion-specimen/logic.js +1 -1
- package/src/web-components/palette-generator/_palette-utils.js +1 -1
- package/src/web-components/palette-generator/logic.js +1 -1
- package/src/web-components/palette-generator/styles.css +1 -1
- package/src/web-components/semantic-palette/_color-math.js +1 -1
- package/src/web-components/semantic-palette/logic.js +13 -9
- package/src/web-components/spacing-specimen/styles.css +1 -1
- package/src/web-components/theme-catalog/logic.js +3 -3
- package/src/web-components/theme-import/catalog/atlassian.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/bootstrap.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/carbon.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/catppuccin-mocha.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/govuk.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/manifest.json +1 -1
- package/src/web-components/theme-import/catalog/material.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/salesforce.tokens.json +2 -2
- package/src/web-components/theme-import/catalog/tailwind.tokens.json +2 -2
- package/src/web-components/type-specimen/logic.js +4 -4
- package/src/web-components/type-specimen/static.html +3 -3
- package/src/web-components/type-specimen/styles.css +1 -1
- /package/src/{web-components/color-picker/_color-utils.js → lib/color-utils.js} +0 -0
|
@@ -25,7 +25,7 @@ var ks=window.matchMedia("(prefers-reduced-motion: reduce)");var jt=new Map;func
|
|
|
25
25
|
<button type="button" class="pg-copy-css" style="padding:0.25rem 0.75rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-surface,#fff);color:var(--color-text,#333);cursor:pointer;font-size:var(--font-size-xs,0.75rem);font-family:inherit">Copy CSS</button>
|
|
26
26
|
</div>`);let v=this.#t;for(let h of[...this.children])h!==v&&(h.classList?.contains("pg-seed-label")||h.remove());if(v&&!this.querySelector(".pg-seed-label")){let h=document.createElement("span");h.className="pg-seed-label",h.textContent="Seed Color",v.before(h)}let b=document.createElement("div");if(b.className=`palette ${e}`,b.setAttribute("role","list"),b.setAttribute("aria-label","Color palette"),b.style.cssText=u,b.innerHTML=d,v?v.after(b):this.prepend(b),y){let h=document.createElement("div");h.innerHTML=y,h.firstElementChild&&this.append(h.firstElementChild)}this.#a(b,a,l,o),i&&this.#l()}#a(t,e,s,o){t.querySelectorAll(".color-box").forEach(n=>{let i=n;o||(i.addEventListener("pointerenter",()=>{let a=i.querySelector(".color-value");a&&(a.style.opacity="1")}),i.addEventListener("pointerleave",()=>{let a=i.querySelector(".color-value");a&&(a.style.opacity="0")})),i.addEventListener("click",()=>{let a=Number(i.dataset.index),l=e[a],c=s[a]||"";w(l,{button:i,announceMessage:"Color copied"}),this.dispatchEvent(new CustomEvent("color-palette:select",{bubbles:!0,detail:{color:l,name:c,index:a}})),i.style.outline="3px solid currentColor",i.style.outlineOffset="2px",setTimeout(()=>{i.style.outline="",i.style.outlineOffset=""},600)})})}#n(){let t=this.#t;t&&(t.tagName==="COLOR-PICKER"?this.listen(t,"color-picker:change",e=>{this.#e=e.detail.hex,this.#i(),this.#d()}):this.listen(t,"input",()=>{this.#e=t.value,this.#i(),this.#d()}))}#l(){let t=this.querySelector(".pg-copy-hex"),e=this.querySelector(".pg-copy-css");t&&t.addEventListener("click",()=>{w(this.#s.join(", "),{button:t,announceMessage:"Hex values copied"})}),e&&e.addEventListener("click",()=>{let s=this.getAttribute("harmony")||"complementary",o=this.#p(s);w(o,{button:e,announceMessage:"CSS variables copied"})})}#c(t){if(t.startsWith("#")){let{r:e,g:s,b:o}=j(t);return .2126*(e/255)+.7152*(s/255)+.0722*(o/255)>.4?"#000":"#fff"}return"#000"}#p(t){return t==="monochromatic"?this.#s.map((e,s)=>`--color-seed-${this.#r[s]||s+1}: ${e};`).join(`
|
|
27
27
|
`):this.#s.map((e,s)=>`--palette-${this.#r[s]?this.#r[s].toLowerCase().replace(/\s+/g,"-"):`${s+1}`}: ${e};`).join(`
|
|
28
|
-
`)}#d(){let t=this.getAttribute("harmony")||"complementary";this.dispatchEvent(new CustomEvent("palette-generator:generate",{bubbles:!0,detail:{colors:[...this.#s],harmony:t,seed:this.#e}}))}};f("palette-generator",Z);var Ae=["system-ui","Georgia","Inter, sans-serif",'"JetBrains Mono", monospace',"Verdana","Cambria","ui-serif"],tt=class extends m{static observedAttributes=["font-family","label","sample","show-scale","show-weights","show-characters","weights","editable","target","token"];setup(){this.#t(),this.#e()}attributeChangedCallback(){this.isConnected&&(this.#t(),this.#e())}#t(){let t=this.getAttribute("font-family")||"system-ui",e=this.getAttribute("label")||t.replace(/['"]/g,"").split(",")[0],s=this.getAttribute("sample")||"The quick brown fox jumps over the lazy dog",o=this.hasAttribute("show-scale"),n=this.hasAttribute("show-weights"),i=this.hasAttribute("show-characters"),l=(this.getAttribute("weights")||"300,400,500,600,700").split(",").map(d=>d.trim()),c="",u=this.hasAttribute("editable")?`<input type="text" class="specimen-font-input" value="${t.replace(/"/g,""")}" aria-label="Font family" style="font:inherit;padding:0.25rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);min-inline-size:18rem;max-inline-size:100%;font-family:${t};font-size:var(--font-size-
|
|
28
|
+
`)}#d(){let t=this.getAttribute("harmony")||"complementary";this.dispatchEvent(new CustomEvent("palette-generator:generate",{bubbles:!0,detail:{colors:[...this.#s],harmony:t,seed:this.#e}}))}};f("palette-generator",Z);var Ae=["system-ui","Georgia","Inter, sans-serif",'"JetBrains Mono", monospace',"Verdana","Cambria","ui-serif"],tt=class extends m{static observedAttributes=["font-family","label","sample","show-scale","show-weights","show-characters","weights","editable","target","token"];setup(){this.#t(),this.#e()}attributeChangedCallback(){this.isConnected&&(this.#t(),this.#e())}#t(){let t=this.getAttribute("font-family")||"system-ui",e=this.getAttribute("label")||t.replace(/['"]/g,"").split(",")[0],s=this.getAttribute("sample")||"The quick brown fox jumps over the lazy dog",o=this.hasAttribute("show-scale"),n=this.hasAttribute("show-weights"),i=this.hasAttribute("show-characters"),l=(this.getAttribute("weights")||"300,400,500,600,700").split(",").map(d=>d.trim()),c="",u=this.hasAttribute("editable")?`<input type="text" class="specimen-font-input" value="${t.replace(/"/g,""")}" aria-label="Font family" style="font:inherit;padding:0.25rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);min-inline-size:18rem;max-inline-size:100%;font-family:${t};font-size:var(--font-size-s,0.875rem)">
|
|
29
29
|
<span class="specimen-quick" style="display:inline-flex;flex-wrap:wrap;gap:0.25rem;margin-inline-start:0.5rem">
|
|
30
30
|
${Ae.map(d=>`<button type="button" class="specimen-quick-btn" data-font="${d.replace(/"/g,""")}" style="font:inherit;font-size:var(--font-size-xs,0.75rem);padding:0.125rem 0.5rem;border:1px solid var(--color-border,#ccc);border-radius:999px;background:var(--color-surface,#fff);color:var(--color-text,#222);cursor:pointer">${d.split(",")[0].replace(/["']/g,"")}</button>`).join("")}
|
|
31
31
|
</span>`:`<span class="specimen-label">${e}</span>`;if(c+=`<div class="specimen-header" style="font-family:${t}">
|
|
@@ -39,7 +39,7 @@ var ks=window.matchMedia("(prefers-reduced-motion: reduce)");var jt=new Map;func
|
|
|
39
39
|
</div>`),n){c+='<div class="specimen-weights">';for(let d of l)c+=`<div class="weight-sample" style="font-family:${t};font-weight:${d}">
|
|
40
40
|
<span class="weight-label">${d}</span>
|
|
41
41
|
<span class="weight-text">Aa</span>
|
|
42
|
-
</div>`;c+="</div>"}if(o){let d=[{name:"xs",rem:.75},{name:"
|
|
42
|
+
</div>`;c+="</div>"}if(o){let d=[{name:"xs",rem:.75},{name:"s",rem:.875},{name:"m",rem:1},{name:"l",rem:1.125},{name:"xl",rem:1.25},{name:"2xl",rem:1.5},{name:"3xl",rem:1.875},{name:"4xl",rem:2.25},{name:"5xl",rem:3}];c+='<div class="specimen-scale">';for(let y of d)c+=`<div class="scale-step" style="font-family:${t};font-size:${y.rem}rem">
|
|
43
43
|
<span class="scale-label">${y.name}</span>
|
|
44
44
|
<span class="scale-text">${s.substring(0,30)}</span>
|
|
45
45
|
</div>`;c+="</div>"}this.innerHTML=c}#e(){if(!this.hasAttribute("editable"))return;let t=this.querySelector(".specimen-font-input");t&&this.listen(t,"input",()=>this.#s(t.value)),this.querySelectorAll(".specimen-quick-btn").forEach(e=>{this.listen(e,"click",()=>{let s=e.getAttribute("data-font")||"";t&&(t.value=s),this.#s(s)})})}#s(t){let e=this.#r(),s=this.getAttribute("token")||"font-family-base";e&&e.style.setProperty(`--${s}`,t),this.setAttribute("font-family",t),this.dispatchEvent(new CustomEvent("type-specimen:change",{bubbles:!0,detail:{fontFamily:t,token:s,target:this.getAttribute("target")||":root"}}))}#r(){let t=this.getAttribute("target")||":root";try{return t===":root"?document.documentElement:document.querySelector(t)}catch{return document.documentElement}}};f("type-specimen",tt);var et=class extends m{static observedAttributes=["tokens","prefix","show-values","label","editable","target"];setup(){this.#t(),this.#e()}attributeChangedCallback(){this.isConnected&&(this.#t(),this.#e())}#t(){let t=this.getAttribute("tokens")||"3xs,2xs,xs,s,m,l,xl,2xl,3xl",e=this.getAttribute("prefix")||"--size-",s=this.getAttribute("show-values")!=="false",o=this.getAttribute("label")||"",n=this.hasAttribute("editable"),i=t.split(",").map(l=>l.trim()),a="";o&&(a+=`<div style="font-size:0.75rem;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--color-text-muted,#666);margin-block-end:0.75rem;font-family:var(--font-sans,system-ui)">${o}</div>`),a+=`<div role="list" aria-label="${o||"Spacing scale"}" style="display:flex;flex-direction:column;gap:0.25rem">`;for(let l of i){let c=`${e}${l}`,p=n?`<input type="text" class="scale-edit" data-token="${l}" aria-label="${l} value" style="font-family:var(--font-mono,monospace);font-size:0.75rem;padding:0.125rem 0.375rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-surface,#fff);color:var(--color-text,#222);inline-size:6rem;text-align:end">`:s?'<span class="scale-value" style="font-family:var(--font-mono,monospace);font-size:0.75rem;color:var(--color-text-muted,#666);font-variant-numeric:tabular-nums;min-inline-size:3.5rem;text-align:end"></span>':"";a+=`<div role="listitem" style="display:grid;grid-template-columns:3rem 1fr auto;align-items:center;gap:0.75rem;min-block-size:1.75rem">
|
|
@@ -113,10 +113,10 @@ var ks=window.matchMedia("(prefers-reduced-motion: reduce)");var jt=new Map;func
|
|
|
113
113
|
<textarea rows="3" placeholder="Textarea sample" aria-label="Sample textarea" style="width:100%"></textarea>`},rt=class extends m{static observedAttributes=["components","label","compact"];setup(){this.#t()}attributeChangedCallback(){this.isConnected&&this.#t()}#t(){let t=this.getAttribute("components")||"button,input,select,checkbox,radio,badge,progress",e=this.getAttribute("label")||"",s=this.hasAttribute("compact"),o=t.split(",").map(a=>a.trim()),n=s?"0.75rem":"1.25rem",i="";e&&(i+=`<p style="font-size:0.75rem;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--color-text-muted,#666);margin-block-end:0.75rem;font-family:var(--font-sans,system-ui)">${e}</p>`),i+=`<section style="display:grid;grid-template-columns:repeat(auto-fit,minmax(14rem,1fr));gap:${n}">`;for(let a of o){let l=je[a];l&&(i+=`<article style="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);padding:var(--size-m,1rem);background:var(--color-surface,#fff)">
|
|
114
114
|
<p style="font-size:0.625rem;font-weight:700;text-transform:uppercase;letter-spacing:0.08em;color:var(--color-text-muted,#999);margin-block-end:var(--size-s,0.5rem);font-family:var(--font-sans,system-ui)">${a}</p>
|
|
115
115
|
${l()}
|
|
116
|
-
</article>`)}i+="</section>",this.innerHTML=i}};f("component-sampler",rt);var ot=r=>r<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4),nt=r=>r<=.0031308?12.92*r:1.055*Math.pow(r,1/2.4)-.055,it=r=>r<0?0:r>1?1:r;function B(r){let{r:t,g:e,b:s}=j(r),o=ot(t/255),n=ot(e/255),i=ot(s/255),a=.4122214708*o+.5363325363*n+.0514459929*i,l=.2119034982*o+.6806995451*n+.1073969566*i,c=.0883024619*o+.2817188376*n+.6299787005*i,p=Math.cbrt(a),u=Math.cbrt(l),d=Math.cbrt(c),y=.2104542553*p+.793617785*u-.0040720468*d,v=1.9779984951*p-2.428592205*u+.4505937099*d,b=.0259040371*p+.7827717662*u-.808675766*d,h=Math.sqrt(v*v+b*b),C=Math.atan2(b,v)*180/Math.PI;return C<0&&(C+=360),{l:y,c:h,h:C}}function I(r,t,e){let s=e*Math.PI/180,o=t*Math.cos(s),n=t*Math.sin(s),i=r+.3963377774*o+.2158037573*n,a=r-.1055613458*o-.0638541728*n,l=r-.0894841775*o-1.291485548*n,c=i*i*i,p=a*a*a,u=l*l*l,d=4.0767416621*c-3.3077115913*p+.2309699292*u,y=-1.2684380046*c+2.6097574011*p-.3413193965*u,v=-.0041960863*c-.7034186147*p+1.707614701*u,b=it(nt(d)),h=it(nt(y)),C=it(nt(v));return P(Math.round(b*255),Math.round(h*255),Math.round(C*255))}function lt(r,t){if(!r)return null;let e=String(r).trim();if(/^#[0-9a-f]{6}$/i.test(e))return e.toLowerCase();if(/^#[0-9a-f]{3}$/i.test(e))return("#"+e.slice(1).split("").map(i=>i+i).join("")).toLowerCase();if(typeof document>"u")return null;let s=t||document.createElement("span");t||(s.style.display="none",document.body.appendChild(s)),s.style.color="",s.style.color=e;let o=getComputedStyle(s).color;t||s.remove();let n=o.match(/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/);return n?P(Math.round(+n[1]),Math.round(+n[2]),Math.round(+n[3])):null}function Ht({l:r,c:t,h:e}){return`oklch(${(r*100).toFixed(1)}% ${t.toFixed(3)} ${e.toFixed(1)})`}function at(r){let{r:t,g:e,b:s}=j(r),o=n=>{let i=n/255;return i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)};return .2126*o(t)+.7152*o(e)+.0722*o(s)}function Pt(r,t){let e=at(r),s=at(t),o=Math.max(e,s),n=Math.min(e,s);return(o+.05)/(n+.05)}function _t(r){return r>=7?"AAA":r>=4.5?"AA":"Fail"}function ct(r){return at(r)>.4?"#000000":"#ffffff"}var V=["primary","secondary","accent"],Wt=["success","warning","error","info"],Be=[...V,...Wt],Vt={primary:"Primary",secondary:"Secondary",accent:"Accent",success:"Success",warning:"Warning",error:"Error",info:"Info"},Oe={aaa:{bg:"oklch(92% 0.08 145)",fg:"oklch(30% 0.12 145)"},aa:{bg:"oklch(94% 0.08 90)",fg:"oklch(35% 0.12 70)"},fail:{bg:"oklch(92% 0.08 25)",fg:"oklch(35% 0.15 25)"}},dt="var(--font-mono, monospace)",pt="var(--color-text-muted, #666)",ut="var(--color-border, #ddd)",Ut="var(--color-surface, #fff)",Fe="var(--color-text, #222)",q="var(--radius-s, 0.25rem)",Ie="var(--radius-m, 0.5rem)",mt=class extends m{static observedAttributes=["colors","roles","show-export","label"];#t=[];#e=[];#s=null;#r=null;#o=null;setup(){this.#o=document.createElement("span"),this.#o.style.cssText="position:absolute;visibility:hidden;pointer-events:none",this.append(this.#o),this.#s=this.querySelector("color-palette, palette-generator"),this.#a(),this.#i(),this.#l(),this.#c("init"),this.#x(),this.#g(),this.#f("init")}attributeChangedCallback(t){!this.isConnected||!this.hasAttribute("data-upgraded")||(t==="roles"&&this.#a(),t==="colors"&&this.#i(),this.#l(),this.#c("attribute"),this.#g(),this.#f("attribute"))}teardown(){this.#o?.remove(),this.#o=null}#i(){let t=this.querySelector("color-palette");if(t){if(typeof t.colors<"u"&&t.colors.length){this.#t=t.colors.slice();return}let n=(t.getAttribute("colors")||"").split(",").map(i=>i.trim()).filter(Boolean);if(n.length){this.#t=n;return}}let e=this.querySelector("palette-generator");if(e){let o=e.getAttribute("seed")||e.querySelector('input[type="color"]')?.value||"",n=e.getAttribute("harmony")||"complementary";if(o)try{let{colors:i}=_(o,n);this.#t=i.slice();return}catch{}}let s=this.getAttribute("colors")||"";this.#t=s.split(",").map(o=>o.trim()).filter(Boolean)}#a(){let e=(this.getAttribute("roles")||V.join(",")).split(",").map(s=>s.trim().toLowerCase()).filter(s=>Be.includes(s));this.#e=e.length?e:[...V]}#n(){let t={};for(let e=0;e<this.#e.length;e++)t[this.#e[e]]=this.#t[e]||this.#t[this.#t.length-1]||"#888888";return t}#l(){let t=this.querySelector(":scope > .sp-shell");t&&t.remove();let e=this.getAttribute("label"),s=this.hasAttribute("show-export"),o=document.createElement("div");if(o.className="sp-shell",o.style.cssText="display:flex;flex-direction:column;gap:var(--size-m,1rem);margin-block-start:var(--size-s,0.75rem)",e){let i=document.createElement("p");i.style.cssText="font-weight:600;margin:0",i.textContent=e,o.append(i)}let n=document.createElement("section");n.className="sp-previews",n.setAttribute("aria-label","Role previews"),n.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(min(22rem,100%),1fr));gap:var(--size-m,1rem)",o.append(n),this.#r=n,s&&o.insertAdjacentHTML("beforeend",this.#v()),this.append(o)}#c(t){if(!this.#r)return;let e=this.#n();this.#r.innerHTML=this.#e.map(s=>this.#p(s,e[s])).join("")}#p(t,e){let s=Vt[t]||t,n=Wt.includes(t)?this.#h(t,e):this.#d(t,e),i=`display:flex;flex-direction:column;gap:var(--size-s,0.75rem);padding:var(--size-m,1rem);border:1px solid ${ut};border-radius:${Ie};background:${Ut};min-inline-size:0`;return`<article class="sp-card" data-role="${t}" aria-label="${s} role preview" style="${i}">
|
|
116
|
+
</article>`)}i+="</section>",this.innerHTML=i}};f("component-sampler",rt);var ot=r=>r<=.04045?r/12.92:Math.pow((r+.055)/1.055,2.4),nt=r=>r<=.0031308?12.92*r:1.055*Math.pow(r,1/2.4)-.055,it=r=>r<0?0:r>1?1:r;function B(r){let{r:t,g:e,b:s}=j(r),o=ot(t/255),n=ot(e/255),i=ot(s/255),a=.4122214708*o+.5363325363*n+.0514459929*i,l=.2119034982*o+.6806995451*n+.1073969566*i,c=.0883024619*o+.2817188376*n+.6299787005*i,p=Math.cbrt(a),u=Math.cbrt(l),d=Math.cbrt(c),y=.2104542553*p+.793617785*u-.0040720468*d,v=1.9779984951*p-2.428592205*u+.4505937099*d,b=.0259040371*p+.7827717662*u-.808675766*d,h=Math.sqrt(v*v+b*b),C=Math.atan2(b,v)*180/Math.PI;return C<0&&(C+=360),{l:y,c:h,h:C}}function I(r,t,e){let s=e*Math.PI/180,o=t*Math.cos(s),n=t*Math.sin(s),i=r+.3963377774*o+.2158037573*n,a=r-.1055613458*o-.0638541728*n,l=r-.0894841775*o-1.291485548*n,c=i*i*i,p=a*a*a,u=l*l*l,d=4.0767416621*c-3.3077115913*p+.2309699292*u,y=-1.2684380046*c+2.6097574011*p-.3413193965*u,v=-.0041960863*c-.7034186147*p+1.707614701*u,b=it(nt(d)),h=it(nt(y)),C=it(nt(v));return P(Math.round(b*255),Math.round(h*255),Math.round(C*255))}function lt(r,t){if(!r)return null;let e=String(r).trim();if(/^#[0-9a-f]{6}$/i.test(e))return e.toLowerCase();if(/^#[0-9a-f]{3}$/i.test(e))return("#"+e.slice(1).split("").map(i=>i+i).join("")).toLowerCase();if(typeof document>"u")return null;let s=t||document.createElement("span");t||(s.style.display="none",document.body.appendChild(s)),s.style.color="",s.style.color=e;let o=getComputedStyle(s).color;t||s.remove();let n=o.match(/rgba?\(\s*([0-9.]+)[\s,]+([0-9.]+)[\s,]+([0-9.]+)/);return n?P(Math.round(+n[1]),Math.round(+n[2]),Math.round(+n[3])):null}function Ht({l:r,c:t,h:e}){return`oklch(${(r*100).toFixed(1)}% ${t.toFixed(3)} ${e.toFixed(1)})`}function at(r){let{r:t,g:e,b:s}=j(r),o=n=>{let i=n/255;return i<=.03928?i/12.92:Math.pow((i+.055)/1.055,2.4)};return .2126*o(t)+.7152*o(e)+.0722*o(s)}function Pt(r,t){let e=at(r),s=at(t),o=Math.max(e,s),n=Math.min(e,s);return(o+.05)/(n+.05)}function _t(r){return r>=7?"AAA":r>=4.5?"AA":"Fail"}function ct(r){return at(r)>.4?"#000000":"#ffffff"}var V=["primary","secondary","accent"],Wt=["success","warning","error","info"],Be=[...V,...Wt],Vt={primary:"Primary",secondary:"Secondary",accent:"Accent",success:"Success",warning:"Warning",error:"Error",info:"Info"},Oe={aaa:{bg:"oklch(92% 0.08 145)",fg:"oklch(30% 0.12 145)"},aa:{bg:"oklch(94% 0.08 90)",fg:"oklch(35% 0.12 70)"},fail:{bg:"oklch(92% 0.08 25)",fg:"oklch(35% 0.15 25)"}},dt="var(--font-mono, monospace)",pt="var(--color-text-muted, #666)",ut="var(--color-border, #ddd)",Ut="var(--color-surface, #fff)",Fe="var(--color-text, #222)",q="var(--radius-s, 0.25rem)",Ie="var(--radius-m, 0.5rem)",mt=class extends m{static observedAttributes=["colors","roles","show-export","label"];#t=[];#e=[];#s=null;#r=null;#o=null;setup(){this.#o?.parentNode!==this&&(this.#o=document.createElement("span"),this.#o.style.cssText="position:absolute;visibility:hidden;pointer-events:none",this.append(this.#o)),this.#s=this.querySelector("color-palette, palette-generator"),this.#a(),this.#i(),this.#l(),this.#c("init"),this.#x(),this.#g(),this.#f("init")}attributeChangedCallback(t){!this.isConnected||!this.hasAttribute("data-upgraded")||(t==="roles"&&this.#a(),t==="colors"&&this.#i(),this.#l(),this.#c("attribute"),this.#g(),this.#f("attribute"))}teardown(){this.#o?.remove(),this.#o=null}#i(){let t=this.querySelector("color-palette");if(t){if(typeof t.colors<"u"&&t.colors.length){this.#t=t.colors.slice();return}let n=(t.getAttribute("colors")||"").split(",").map(i=>i.trim()).filter(Boolean);if(n.length){this.#t=n;return}}let e=this.querySelector("palette-generator");if(e){let o=e.getAttribute("seed")||e.querySelector('input[type="color"]')?.value||"",n=e.getAttribute("harmony")||"complementary";if(o)try{let{colors:i}=_(o,n);this.#t=i.slice();return}catch{}}let s=this.getAttribute("colors")||"";this.#t=s.split(",").map(o=>o.trim()).filter(Boolean)}#a(){let e=(this.getAttribute("roles")||V.join(",")).split(",").map(s=>s.trim().toLowerCase()).filter(s=>Be.includes(s));this.#e=e.length?e:[...V]}#n(){let t={};for(let e=0;e<this.#e.length;e++)t[this.#e[e]]=this.#t[e]||this.#t[this.#t.length-1]||"#888888";return t}#l(){let t=this.querySelector(":scope > .sp-shell");t&&t.remove();let e=this.getAttribute("label"),s=this.hasAttribute("show-export"),o=document.createElement("div");if(o.className="sp-shell",o.style.cssText="display:flex;flex-direction:column;gap:var(--size-m,1rem);margin-block-start:var(--size-s,0.75rem)",e){let i=document.createElement("p");i.style.cssText="font-weight:600;margin:0",i.textContent=e,o.append(i)}let n=document.createElement("section");n.className="sp-previews",n.setAttribute("aria-label","Role previews"),n.style.cssText="display:grid;grid-template-columns:repeat(auto-fill,minmax(min(22rem,100%),1fr));gap:var(--size-m,1rem)",o.append(n),this.#r=n,s&&o.insertAdjacentHTML("beforeend",this.#v()),this.append(o)}#c(t){if(!this.#r)return;let e=this.#n();this.#r.innerHTML=this.#e.map(s=>this.#p(s,e[s])).join("")}#p(t,e){let s=Vt[t]||t,n=Wt.includes(t)?this.#h(t,e):this.#d(t,e),i=`display:flex;flex-direction:column;gap:var(--size-s,0.75rem);padding:var(--size-m,1rem);border:1px solid ${ut};border-radius:${Ie};background:${Ut};min-inline-size:0`;return`<article class="sp-card" data-role="${t}" aria-label="${s} role preview" style="${i}">
|
|
117
117
|
<header style="display:flex;align-items:center;justify-content:space-between;gap:var(--size-s,0.75rem)">
|
|
118
118
|
<div>
|
|
119
|
-
<code style="font-family:${dt};font-size:var(--font-size-
|
|
119
|
+
<code style="font-family:${dt};font-size:var(--font-size-s,0.875rem);font-weight:600">${t}</code>
|
|
120
120
|
<span style="display:block;font-size:var(--font-size-xs,0.75rem);color:${pt}">${s}</span>
|
|
121
121
|
</div>
|
|
122
122
|
<div style="display:flex;align-items:center;gap:0.5rem">
|
|
@@ -125,16 +125,16 @@ var ks=window.matchMedia("(prefers-reduced-motion: reduce)");var jt=new Map;func
|
|
|
125
125
|
</div>
|
|
126
126
|
</header>
|
|
127
127
|
<div class="sp-samples" style="display:flex;flex-wrap:wrap;gap:var(--size-s,0.75rem);align-items:flex-start">${n}</div>
|
|
128
|
-
</article>`}#d(t,e){let s=this.#$(t,e),o=this.#y(),n=this.#w(t,e),i=this.#S(e);return[this.#u({render:`<button type="button" tabindex="-1" style="all:unset;display:inline-block;padding:0.375rem 0.875rem;border-radius:${q};background:${e};color:${s};font-family:inherit;font-size:var(--font-size-
|
|
128
|
+
</article>`}#d(t,e){let s=this.#$(t,e),o=this.#y(),n=this.#w(t,e),i=this.#S(e);return[this.#u({render:`<button type="button" tabindex="-1" style="all:unset;display:inline-block;padding:0.375rem 0.875rem;border-radius:${q};background:${e};color:${s};font-family:inherit;font-size:var(--font-size-s,0.875rem);font-weight:600;cursor:default">Button</button>`,fg:s,bg:e,caption:"On role"}),this.#u({render:`<span style="color:${e};background:${o};padding:0.25rem 0.5rem;border-radius:${q};font-size:var(--font-size-s,0.875rem);font-weight:500;text-decoration:underline">Linked text</span>`,fg:e,bg:o||"#ffffff",caption:"On surface"}),this.#u({render:`<span style="display:inline-block;padding:0.125rem 0.5rem;border-radius:999px;background:${n};color:${i};font-size:var(--font-size-xs,0.75rem);font-weight:600;letter-spacing:0.04em;text-transform:uppercase">Badge</span>`,fg:i,bg:n,caption:"Subtle"})].join("")}#h(t,e){let s=this.#y(),o=this.#k(t,e),n=this.#z(t,e),i=ct(e);return[this.#u({render:`<div style="display:flex;align-items:center;gap:0.5rem;padding:0.5rem 0.75rem;border-radius:${q};background:${o};color:${n};border:1px solid ${e};font-size:var(--font-size-s,0.875rem);max-inline-size:100%">
|
|
129
129
|
<span style="display:inline-block;inline-size:0.5rem;block-size:0.5rem;border-radius:50%;background:${e};flex-shrink:0"></span>
|
|
130
130
|
<span><strong>${Vt[t]||t}</strong> \u2014 message text</span>
|
|
131
|
-
</div>`,fg:n,bg:o,caption:"Alert"}),this.#u({render:`<span style="display:inline-block;padding:0.125rem 0.5rem;border-radius:999px;background:${e};color:${i};font-size:var(--font-size-xs,0.75rem);font-weight:700;letter-spacing:0.04em;text-transform:uppercase">${t}</span>`,fg:i,bg:e,caption:"Badge"}),this.#u({render:`<span style="color:${e};background:${s};padding:0.25rem 0.5rem;border-radius:${q};font-size:var(--font-size-
|
|
131
|
+
</div>`,fg:n,bg:o,caption:"Alert"}),this.#u({render:`<span style="display:inline-block;padding:0.125rem 0.5rem;border-radius:999px;background:${e};color:${i};font-size:var(--font-size-xs,0.75rem);font-weight:700;letter-spacing:0.04em;text-transform:uppercase">${t}</span>`,fg:i,bg:e,caption:"Badge"}),this.#u({render:`<span style="color:${e};background:${s};padding:0.25rem 0.5rem;border-radius:${q};font-size:var(--font-size-s,0.875rem);font-weight:600">Inline status</span>`,fg:e,bg:s||"#ffffff",caption:"On surface"})].join("")}#u({render:t,fg:e,bg:s,caption:o}){let n=lt(e,this.#o||void 0)||"#000000",i=lt(s,this.#o||void 0)||"#ffffff",a=Pt(n,i),l=_t(a).toLowerCase(),c=Oe[l],p=`display:inline-flex;align-items:center;gap:0.25rem;padding:0.125rem 0.375rem;border-radius:${q};font-family:${dt};font-size:var(--font-size-xs,0.75rem);background:${c.bg};color:${c.fg}`;return`<div style="display:flex;flex-direction:column;gap:0.25rem;align-items:flex-start;min-inline-size:0;max-inline-size:100%">
|
|
132
132
|
<div style="max-inline-size:100%">${t}</div>
|
|
133
133
|
<div style="display:flex;align-items:center;gap:0.375rem;font-size:var(--font-size-xs,0.75rem);color:${pt}">
|
|
134
134
|
<span style="${p}" title="${o}: ${a.toFixed(2)}:1">${a.toFixed(2)} <small>${l.toUpperCase()}</small></span>
|
|
135
135
|
<span>${o}</span>
|
|
136
136
|
</div>
|
|
137
|
-
</div>`}#v(){let t=`display:flex;gap:var(--size-2xs,0.375rem);padding-block-start:var(--size-xs,0.5rem);border-block-start:1px solid ${ut}`,e=`padding:0.375rem 0.875rem;border:1px solid ${ut};border-radius:${q};background:${Ut};color:${Fe};cursor:pointer;font:inherit;font-size:var(--font-size-
|
|
137
|
+
</div>`}#v(){let t=`display:flex;gap:var(--size-2xs,0.375rem);padding-block-start:var(--size-xs,0.5rem);border-block-start:1px solid ${ut}`,e=`padding:0.375rem 0.875rem;border:1px solid ${ut};border-radius:${q};background:${Ut};color:${Fe};cursor:pointer;font:inherit;font-size:var(--font-size-s,0.875rem)`;return`<div class="sp-export" role="toolbar" aria-label="Export semantic palette" style="${t}">
|
|
138
138
|
<button type="button" class="sp-copy-css" style="${e}">Copy Theme CSS</button>
|
|
139
139
|
<button type="button" class="sp-copy-json" style="${e}">Copy JSON</button>
|
|
140
140
|
</div>`}#x(){let t=this.querySelector("color-palette");t&&this.listen(t,"color-palette:change",()=>{this.#i(),this.#c("palette"),this.#f("palette")});let e=this.querySelector("palette-generator");e&&this.listen(e,"palette-generator:generate",()=>{this.#i(),this.#c("palette"),this.#f("palette")})}#g(){let t=this.querySelector(".sp-copy-css"),e=this.querySelector(".sp-copy-json");t&&this.listen(t,"click",()=>{w(this.#b(),{button:t,announceMessage:"Theme CSS copied"})}),e&&this.listen(e,"click",()=>{w(JSON.stringify(this.#n(),null,2),{button:e,announceMessage:"JSON copied"})})}#m(){return getComputedStyle(this)}#y(){return this.#m().getPropertyValue("--color-surface").trim()||"#ffffff"}#$(t,e){return this.#m().getPropertyValue(`--color-text-on-${t}`).trim()||ct(e)}#w(t,e){let s=this.#m().getPropertyValue(`--color-${t}-subtle`).trim();if(s)return s;let{h:o}=B(e);return I(.95,.03,o)}#k(t,e){let s=this.#m().getPropertyValue(`--color-${t}-subtle`).trim();if(s)return s;let{h:o}=B(e);return I(.94,.05,o)}#z(t,e){let s=this.#m().getPropertyValue(`--color-${t}-text`).trim();if(s)return s;let{h:o}=B(e);return I(.3,.14,o)}#S(t){let{l:e,c:s,h:o}=B(t);return I(Math.max(.2,e-.25),s,o)}#b(){let t=this.#n(),e=[],s=[];for(let n of this.#e){let i=t[n];if(!i)continue;let{l:a,c:l,h:c}=B(i);V.includes(n)?e.push(` --hue-${n}: ${c.toFixed(1)};`,` --lightness-${n}: ${(a*100).toFixed(1)}%;`,` --chroma-${n}: ${l.toFixed(3)};`):s.push(` --color-${n}: ${Ht({l:a,c:l,h:c})};`)}let o=[];return e.length&&o.push(" /* Brand seeds */",...e),s.length&&(e.length&&o.push(""),o.push(" /* Status colors */",...s)),`:root {
|
|
@@ -148,7 +148,7 @@ ${o.join(`
|
|
|
148
148
|
motion-specimen .ms-dot { animation: none !important; inset-inline-start: calc(50% - 0.5rem) !important }
|
|
149
149
|
motion-specimen .ms-bar-fill { animation: none !important; transform: scaleX(0.6) !important; opacity: 0.6 !important }
|
|
150
150
|
}
|
|
151
|
-
`;function Pe(){if(typeof document>"u"||document.getElementById(Gt))return;let r=document.createElement("style");r.id=Gt,r.textContent=He,document.head.append(r)}var Jt="var(--font-mono, monospace)",Kt="var(--color-text-muted, #666)",Xt="var(--color-interactive, oklch(55% 0.2 260))",Yt="var(--color-surface-sunken, #f1f1f1)",ht=class extends m{static observedAttributes=["type","tokens","prefix","duration","show-values","label"];setup(){Pe(),this.#t()}attributeChangedCallback(){this.isConnected&&this.hasAttribute("data-upgraded")&&this.#t()}#t(){let t=this.getAttribute("type")||"easing",e=this.getAttribute("duration")||"1.2s",s=this.getAttribute("show-values")!=="false",o=this.getAttribute("label")||"",n="";o&&(n+=`<p style="font-weight:600;margin:0 0 var(--size-s,0.75rem)">${o}</p>`),(t==="easing"||t==="both")&&(n+=this.#i(e,s)),(t==="duration"||t==="both")&&(t==="both"&&(n+='<div aria-hidden="true" style="block-size:var(--size-m,1rem)"></div>'),n+=this.#a(s)),this.innerHTML=n,s&&requestAnimationFrame(()=>this.#n())}#e(){return"display:grid;grid-template-columns:5rem 1fr auto;align-items:center;gap:var(--size-s,0.75rem);min-block-size:1.75rem"}#s(){return`font-family:${Jt};font-size:var(--font-size-
|
|
151
|
+
`;function Pe(){if(typeof document>"u"||document.getElementById(Gt))return;let r=document.createElement("style");r.id=Gt,r.textContent=He,document.head.append(r)}var Jt="var(--font-mono, monospace)",Kt="var(--color-text-muted, #666)",Xt="var(--color-interactive, oklch(55% 0.2 260))",Yt="var(--color-surface-sunken, #f1f1f1)",ht=class extends m{static observedAttributes=["type","tokens","prefix","duration","show-values","label"];setup(){Pe(),this.#t()}attributeChangedCallback(){this.isConnected&&this.hasAttribute("data-upgraded")&&this.#t()}#t(){let t=this.getAttribute("type")||"easing",e=this.getAttribute("duration")||"1.2s",s=this.getAttribute("show-values")!=="false",o=this.getAttribute("label")||"",n="";o&&(n+=`<p style="font-weight:600;margin:0 0 var(--size-s,0.75rem)">${o}</p>`),(t==="easing"||t==="both")&&(n+=this.#i(e,s)),(t==="duration"||t==="both")&&(t==="both"&&(n+='<div aria-hidden="true" style="block-size:var(--size-m,1rem)"></div>'),n+=this.#a(s)),this.innerHTML=n,s&&requestAnimationFrame(()=>this.#n())}#e(){return"display:grid;grid-template-columns:5rem 1fr auto;align-items:center;gap:var(--size-s,0.75rem);min-block-size:1.75rem"}#s(){return`font-family:${Jt};font-size:var(--font-size-s,0.875rem);color:${Kt};text-align:end`}#r(){return`font-family:${Jt};font-size:var(--font-size-xs,0.75rem);color:${Kt};font-variant-numeric:tabular-nums;white-space:nowrap`}#o(){return"list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem)"}#i(t,e){let s=(this.getAttribute("tokens")||Re).split(",").map(l=>l.trim()),o=this.getAttribute("prefix")||"--ease-",n=`position:relative;display:block;block-size:0.5rem;background:${Yt};border-radius:999px`,i=`position:absolute;inset-block-start:50%;inset-inline-start:0;inline-size:1rem;block-size:1rem;background:${Xt};border-radius:50%;transform:translateY(-50%)`,a=s.map(l=>{let c=`${o}${l}`;return`<li class="ms-row ms-row-ease" role="listitem" style="${this.#e()}">
|
|
152
152
|
<span style="${this.#s()}">${l}</span>
|
|
153
153
|
<span style="${n}" aria-hidden="true">
|
|
154
154
|
<span class="ms-dot" style="${i};animation: ms-slide ${t} var(${c}) infinite alternate"></span>
|
|
@@ -253,36 +253,36 @@ ${o}
|
|
|
253
253
|
</layout-text>`,render:()=>g("layout-text",{},[g("p",{style:"margin: 0; font-size: 0.85em"},["This paragraph is constrained to a comfortable reading measure (~60ch) regardless of the parent width."])])}];function g(r,t={},e=[]){let s=document.createElement(r);for(let[o,n]of Object.entries(t))n!=null&&(o==="style"?s.setAttribute("style",n):s.setAttribute(o,n===!0?"":String(n)));for(let o of e)typeof o=="string"?s.appendChild(document.createTextNode(o)):o&&s.appendChild(o);return s}function x(r,t){return g("div",{class:`ls-box${t?` ls-box-${t}`:""}`},[r])}function W(r){return g("span",{class:"ls-chip"},[r])}var wt=class extends m{setup(){let t=this.getAttribute("data-only"),e=t?new Set(t.split(",").map(o=>o.trim())):null,s=ds.filter(o=>!e||e.has(o.name)||e.has(o.name.replace(/^layout-/,"")));this.replaceChildren();for(let o of s)this.appendChild(this.#t(o))}#t(t){let e=g("section",{class:"ls-entry"}),s=g("header",{class:"ls-entry-head"},[g("h3",{class:"ls-entry-name"},[t.name]),g("p",{class:"ls-entry-desc"},[t.desc])]),o=g("div",{class:"ls-live"});o.appendChild(t.render());let n=g("pre",{class:"ls-snippet"},[g("code",{},[t.snippet])]);return e.append(s,o,n),e}};f("layout-specimen",wt);var D=[{name:"Playfair Display",category:"serif",weights:"400;600;700;900",style:"elegant"},{name:"Merriweather",category:"serif",weights:"300;400;700;900",style:"readable"},{name:"Lora",category:"serif",weights:"400;500;600;700",style:"elegant"},{name:"Source Serif 4",category:"serif",weights:"300;400;600;700",style:"neutral"},{name:"Libre Baskerville",category:"serif",weights:"400;700",style:"classic"},{name:"Crimson Text",category:"serif",weights:"400;600;700",style:"classic"},{name:"DM Serif Display",category:"serif",weights:"400",style:"bold"},{name:"Cormorant Garamond",category:"serif",weights:"300;400;500;600;700",style:"elegant"},{name:"Inter",category:"sans-serif",weights:"300;400;500;600;700",style:"neutral"},{name:"Open Sans",category:"sans-serif",weights:"300;400;600;700",style:"friendly"},{name:"Roboto",category:"sans-serif",weights:"300;400;500;700",style:"neutral"},{name:"Lato",category:"sans-serif",weights:"300;400;700;900",style:"warm"},{name:"Nunito",category:"sans-serif",weights:"300;400;600;700",style:"friendly"},{name:"Work Sans",category:"sans-serif",weights:"300;400;500;600;700",style:"geometric"},{name:"DM Sans",category:"sans-serif",weights:"400;500;700",style:"geometric"},{name:"Plus Jakarta Sans",category:"sans-serif",weights:"300;400;500;600;700",style:"modern"},{name:"Space Grotesk",category:"sans-serif",weights:"300;400;500;600;700",style:"technical"},{name:"Manrope",category:"sans-serif",weights:"300;400;500;600;700",style:"geometric"},{name:"IBM Plex Sans",category:"sans-serif",weights:"300;400;500;600",style:"technical"},{name:"Outfit",category:"sans-serif",weights:"300;400;500;600;700",style:"modern"},{name:"Bebas Neue",category:"display",weights:"400",style:"bold"},{name:"Abril Fatface",category:"display",weights:"400",style:"elegant"},{name:"Oswald",category:"display",weights:"300;400;500;600;700",style:"condensed"},{name:"Sora",category:"display",weights:"300;400;500;600;700",style:"modern"},{name:"Fraunces",category:"display",weights:"300;400;500;600;700;900",style:"elegant"},{name:"JetBrains Mono",category:"monospace",weights:"400;500;600;700",style:"technical"},{name:"Fira Code",category:"monospace",weights:"300;400;500;600;700",style:"technical"},{name:"IBM Plex Mono",category:"monospace",weights:"400;500;600",style:"technical"},{name:"Source Code Pro",category:"monospace",weights:"300;400;500;600;700",style:"neutral"}],se=[["Playfair Display","Inter"],["DM Serif Display","DM Sans"],["Fraunces","Plus Jakarta Sans"],["Lora","Open Sans"],["Merriweather","Roboto"],["Oswald","Lato"],["Cormorant Garamond","Work Sans"],["Sora","Inter"],["Abril Fatface","Nunito"],["Source Serif 4","Source Code Pro"],["Space Grotesk","IBM Plex Sans"],["Outfit","Manrope"]];function kt(r,t="400;700"){return`https://fonts.googleapis.com/css2?family=${r.replace(/\s+/g,"+")}:wght@${t}&display=swap`}async function re(r,t="400;700"){let e=`gf-${r.replace(/\s+/g,"-").toLowerCase()}`;if(document.getElementById(e)){await document.fonts.ready;return}let s=document.createElement("link");s.id=e,s.rel="stylesheet",s.href=kt(r,t),document.head.appendChild(s),await document.fonts.ready}var $=(r,t,e,s="")=>`${s} contenteditable="plaintext-only" spellcheck="false" class="fp-editable" data-role="${e}"`,zt={combined:{label:"Combined",render:(r,t)=>`
|
|
254
254
|
<p style="font-family:${r.display};font-size:var(--font-size-3xl,2rem);font-weight:800;margin:0;line-height:1.15"
|
|
255
255
|
${$(r.display,"p","heading")}>${t.heading}</p>
|
|
256
|
-
<h3 style="font-family:${r.heading};font-size:var(--font-size-
|
|
256
|
+
<h3 style="font-family:${r.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0"
|
|
257
257
|
${$(r.heading,"h3","subheading")}>${t.subheading}</h3>
|
|
258
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
258
|
+
<p style="font-family:${r.body};font-size:var(--font-size-m,1rem);line-height:1.65;margin:0;color:var(--color-text-muted,#666)"
|
|
259
259
|
${$(r.body,"p","body")}>${t.body}</p>
|
|
260
|
-
<pre style="font-family:${r.code};font-size:var(--font-size-
|
|
260
|
+
<pre style="font-family:${r.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code ${$(r.code,"code","code")}>${t.code}</code></pre>`},article:{label:"Article",render:(r,t)=>`
|
|
261
261
|
<small style="font-family:${r.body};font-size:var(--font-size-xs,0.75rem);text-transform:uppercase;letter-spacing:0.08em;color:var(--color-interactive,oklch(55% .2 260));font-weight:600"
|
|
262
262
|
${$(r.body,"small","eyebrow")}>${t.eyebrow}</small>
|
|
263
263
|
<h2 style="font-family:${r.heading};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0;line-height:1.2"
|
|
264
264
|
${$(r.heading,"h2","heading")}>${t.heading}</h2>
|
|
265
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
265
|
+
<p style="font-family:${r.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0"
|
|
266
266
|
${$(r.body,"p","byline")}>${t.byline}</p>
|
|
267
267
|
<p style="font-family:${r.body};line-height:1.7;margin:0" ${$(r.body,"p","body")}>${t.body}</p>
|
|
268
|
-
<h3 style="font-family:${r.heading};font-size:var(--font-size-
|
|
268
|
+
<h3 style="font-family:${r.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0"
|
|
269
269
|
${$(r.heading,"h3","subheading")}>${t.subheading}</h3>
|
|
270
270
|
<p style="font-family:${r.body};line-height:1.7;margin:0" ${$(r.body,"p","body2")}>${t.body2}</p>
|
|
271
|
-
<blockquote style="font-family:${r.display};font-style:italic;font-size:var(--font-size-
|
|
271
|
+
<blockquote style="font-family:${r.display};font-style:italic;font-size:var(--font-size-l,1.125rem);border-inline-start:3px solid var(--color-interactive,oklch(55% .2 260));padding-inline-start:var(--size-m,1rem);margin:0;color:var(--color-text-muted,#666)"
|
|
272
272
|
${$(r.display,"blockquote","quote")}>${t.quote}</blockquote>
|
|
273
|
-
<pre style="font-family:${r.code};font-size:var(--font-size-
|
|
273
|
+
<pre style="font-family:${r.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code ${$(r.code,"code","code")}>${t.code}</code></pre>`},"long-article":{label:"Long Article",render:(r,t)=>`
|
|
274
274
|
<small style="font-family:${r.body};font-size:var(--font-size-xs,0.75rem);text-transform:uppercase;letter-spacing:0.08em;color:var(--color-interactive,oklch(55% .2 260));font-weight:600">${t.eyebrow}</small>
|
|
275
275
|
<h1 style="font-family:${r.display};font-size:var(--font-size-3xl,2rem);font-weight:800;margin:0;line-height:1.15">${t.heading}</h1>
|
|
276
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
277
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
276
|
+
<p style="font-family:${r.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0">${t.byline}</p>
|
|
277
|
+
<p style="font-family:${r.body};font-size:var(--font-size-l,1.125rem);line-height:1.6;margin:0;color:var(--color-text-muted,#666)">${t.lead}</p>
|
|
278
278
|
<h2 style="font-family:${r.heading};font-size:var(--font-size-xl,1.375rem);font-weight:700;margin:0">${t.subheading}</h2>
|
|
279
279
|
<p style="font-family:${r.body};line-height:1.7;margin:0">${t.body}</p>
|
|
280
280
|
<p style="font-family:${r.body};line-height:1.7;margin:0">${t.body2}</p>
|
|
281
|
-
<blockquote style="font-family:${r.display};font-style:italic;font-size:var(--font-size-
|
|
281
|
+
<blockquote style="font-family:${r.display};font-style:italic;font-size:var(--font-size-l,1.125rem);border-inline-start:3px solid var(--color-interactive,oklch(55% .2 260));padding-inline-start:var(--size-m,1rem);margin:0;color:var(--color-text-muted,#666)">${t.quote}</blockquote>
|
|
282
282
|
<h2 style="font-family:${r.heading};font-size:var(--font-size-xl,1.375rem);font-weight:700;margin:0">Implementation Details</h2>
|
|
283
283
|
<p style="font-family:${r.body};line-height:1.7;margin:0">Design tokens form the atomic layer of any visual system. Colors, spacing, typography, and motion are expressed as named variables that cascade through every component. When a token changes, every surface that references it updates automatically \u2014 no find-and-replace, no missed instances.</p>
|
|
284
|
-
<pre style="font-family:${r.code};font-size:var(--font-size-
|
|
285
|
-
<h3 style="font-family:${r.heading};font-size:var(--font-size-
|
|
284
|
+
<pre style="font-family:${r.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code>${t.code}</code></pre>
|
|
285
|
+
<h3 style="font-family:${r.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0">Key Takeaways</h3>
|
|
286
286
|
<ul style="font-family:${r.body};line-height:1.7;margin:0;padding-inline-start:1.5rem">
|
|
287
287
|
<li>Typography sets the emotional tone before a single word is read</li>
|
|
288
288
|
<li>Pair contrast with harmony \u2014 serif headings with sans-serif body</li>
|
|
@@ -293,13 +293,13 @@ ${o}
|
|
|
293
293
|
<div style="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-xs,0.5rem)">
|
|
294
294
|
<h4 style="font-family:${r.heading};font-weight:600;margin:0" ${$(r.heading,"h4","cardTitle")}>Premium Plan</h4>
|
|
295
295
|
<p style="font-family:${r.display};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0">$49<small style="font-size:0.5em;font-weight:400">/mo</small></p>
|
|
296
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
296
|
+
<p style="font-family:${r.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0" ${$(r.body,"p","cardBody")}>Everything you need to build faster.</p>
|
|
297
297
|
<code style="font-family:${r.code};font-size:var(--font-size-xs,0.75rem);background:var(--color-surface-sunken,#eee);padding:0.2rem 0.4rem;border-radius:0.25rem" ${$(r.code,"code","cardCode")}>npm install acme</code>
|
|
298
298
|
</div>
|
|
299
299
|
<div style="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-xs,0.5rem)">
|
|
300
300
|
<h4 style="font-family:${r.heading};font-weight:600;margin:0">Enterprise</h4>
|
|
301
301
|
<p style="font-family:${r.display};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0">Custom</p>
|
|
302
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
302
|
+
<p style="font-family:${r.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0">Dedicated support and SLA guarantees.</p>
|
|
303
303
|
<code style="font-family:${r.code};font-size:var(--font-size-xs,0.75rem);background:var(--color-surface-sunken,#eee);padding:0.2rem 0.4rem;border-radius:0.25rem">contact@acme.dev</code>
|
|
304
304
|
</div>
|
|
305
305
|
</div>`},hero:{label:"Hero",render:(r,t)=>`
|
|
@@ -308,13 +308,13 @@ ${o}
|
|
|
308
308
|
${$(r.body,"p","eyebrow")}>${t.eyebrow}</p>
|
|
309
309
|
<h1 style="font-family:${r.display};font-size:clamp(2rem,5vw,3rem);font-weight:800;margin:0;line-height:1.1"
|
|
310
310
|
${$(r.display,"h1","heading")}>${t.heading}</h1>
|
|
311
|
-
<p style="font-family:${r.body};font-size:var(--font-size-
|
|
311
|
+
<p style="font-family:${r.body};font-size:var(--font-size-l,1.125rem);color:var(--color-text-muted,#666);margin:var(--size-s,0.75rem) auto 0;max-width:40ch"
|
|
312
312
|
${$(r.body,"p","body")}>${t.body}</p>
|
|
313
313
|
</div>`}},St=class extends m{static observedAttributes=["heading-font","body-font","code-font","display-font","sample","show-export","show-suggestions","preview"];#t={heading:"",body:"",code:"",display:""};#e="combined";#s={heading:"The Art of Typography",subheading:"Building visual harmony through font pairing",body:"Good typography is invisible \u2014 it lets the content speak without distraction. The best font pairings create harmony between heading impact and body readability. Every typeface carries personality: serif fonts convey trust and tradition, while sans-serif fonts feel modern and clean.",body2:"Choosing the right pairing is about contrast and complement. A bold display font for headlines needs a quiet, readable body font to balance it. Monospace fonts ground technical content in precision. The interplay between these roles defines your brand voice.",code:`const theme = {
|
|
314
314
|
heading: "Playfair Display",
|
|
315
315
|
body: "Inter",
|
|
316
316
|
tokens: { size: 16, scale: 1.25 }
|
|
317
|
-
};`,eyebrow:"Design Systems",byline:"By Jamie Chen \xB7 April 14, 2026 \xB7 8 min read",lead:"How native CSS features and design tokens are replacing the complex tooling we thought we needed.",quote:'"Good typography is invisible \u2014 it lets the content breathe."'};setup(){this.#t.heading=this.getAttribute("heading-font")||"Playfair Display",this.#t.body=this.getAttribute("body-font")||"Inter",this.#t.code=this.getAttribute("code-font")||"JetBrains Mono",this.#t.display=this.getAttribute("display-font")||this.#t.heading,this.#e=this.getAttribute("preview")||"combined",this.#o(),this.#r()}attributeChangedCallback(t,e,s){e===s||!this.isConnected||(t==="heading-font"&&(this.#t.heading=s||"Playfair Display"),t==="body-font"&&(this.#t.body=s||"Inter"),t==="code-font"&&(this.#t.code=s||"JetBrains Mono"),t==="display-font"&&(this.#t.display=s||this.#t.heading),t==="preview"&&(this.#e=s||"combined"),this.#o(),this.#r())}async#r(){let t=Object.values(this.#t).filter(Boolean).map(e=>{let s=D.find(o=>o.name===e);return re(e,s?.weights||"400;700")});await Promise.all(t),this.#p()}#o(){let t=this.hasAttribute("show-export"),e=this.hasAttribute("show-suggestions"),s="var(--size-m, 1rem)",o="var(--size-s, 0.75rem)",n="var(--size-xs, 0.5rem)",i="var(--radius-m, 0.5rem)",a="var(--color-border, #ddd)",l="var(--color-surface, #fff)",c="var(--color-surface-raised, #f5f5f5)",p="var(--color-text-muted, #666)",u="var(--font-size-
|
|
317
|
+
};`,eyebrow:"Design Systems",byline:"By Jamie Chen \xB7 April 14, 2026 \xB7 8 min read",lead:"How native CSS features and design tokens are replacing the complex tooling we thought we needed.",quote:'"Good typography is invisible \u2014 it lets the content breathe."'};setup(){this.#t.heading=this.getAttribute("heading-font")||"Playfair Display",this.#t.body=this.getAttribute("body-font")||"Inter",this.#t.code=this.getAttribute("code-font")||"JetBrains Mono",this.#t.display=this.getAttribute("display-font")||this.#t.heading,this.#e=this.getAttribute("preview")||"combined",this.#o(),this.#r()}attributeChangedCallback(t,e,s){e===s||!this.isConnected||(t==="heading-font"&&(this.#t.heading=s||"Playfair Display"),t==="body-font"&&(this.#t.body=s||"Inter"),t==="code-font"&&(this.#t.code=s||"JetBrains Mono"),t==="display-font"&&(this.#t.display=s||this.#t.heading),t==="preview"&&(this.#e=s||"combined"),this.#o(),this.#r())}async#r(){let t=Object.values(this.#t).filter(Boolean).map(e=>{let s=D.find(o=>o.name===e);return re(e,s?.weights||"400;700")});await Promise.all(t),this.#p()}#o(){let t=this.hasAttribute("show-export"),e=this.hasAttribute("show-suggestions"),s="var(--size-m, 1rem)",o="var(--size-s, 0.75rem)",n="var(--size-xs, 0.5rem)",i="var(--radius-m, 0.5rem)",a="var(--color-border, #ddd)",l="var(--color-surface, #fff)",c="var(--color-surface-raised, #f5f5f5)",p="var(--color-text-muted, #666)",u="var(--font-size-s, 0.875rem)",d="var(--font-size-xs, 0.75rem)",y=`font:inherit;font-size:${u};padding:0.35rem 0.5rem;border:1px solid ${a};border-radius:4px;background:${l}`,b=[{key:"heading",label:"Heading"},{key:"body",label:"Body"},{key:"code",label:"Code"},{key:"display",label:"Display"}].map(E=>`
|
|
318
318
|
<label style="display:flex;flex-direction:column;gap:3px;flex:1;min-width:9rem;font-size:${d};font-weight:600;color:${p};text-transform:uppercase;letter-spacing:0.04em">
|
|
319
319
|
${E.label}
|
|
320
320
|
<select class="fp-select" data-role="${E.key}" style="${y}">
|
|
@@ -356,7 +356,7 @@ ${o}
|
|
|
356
356
|
</aside>
|
|
357
357
|
</div>`:this.innerHTML=H,this.#l()}#i(t){return["serif","sans-serif","display","monospace"].map(s=>{let n=D.filter(i=>i.category===s).map(i=>`<option value="${i.name}"${i.name===t?" selected":""}>${i.name}</option>`).join("");return`<optgroup label="${s}">${n}</optgroup>`}).join("")}#a(){let t=[],e={heading:"serif",body:"sans-serif",code:"monospace",display:"serif"};for(let[s,o]of Object.entries(e)){let n=this.#t[s];if(!n)continue;let i=D.find(a=>a.name===n);t.push(`--font-${s}: "${n}", ${i?.category||o};`)}return t.join(`
|
|
358
358
|
`)}#n(){let t=new Set,e=[];for(let s of Object.values(this.#t)){if(!s||t.has(s))continue;t.add(s);let o=D.find(n=>n.name===s);e.push(`@import url('${kt(s,o?.weights||"400;700")}');`)}return e.join(`
|
|
359
|
-
`)}#l(){this.querySelectorAll(".fp-select").forEach(t=>{t.addEventListener("change",e=>{let s=e.target;this.#t[s.dataset.role]=s.value,this.#r(),this.#c(),this.#d(),this.#h()})}),this.querySelectorAll(".fp-tab").forEach(t=>{t.addEventListener("click",()=>{let e=t;this.#e=e.dataset.mode||"combined",this.#o(),this.#r()})}),this.querySelectorAll(".fp-suggestion").forEach(t=>{t.addEventListener("click",()=>{let e=t;this.#t.heading=e.dataset.h||"",this.#t.body=e.dataset.b||"",this.#t.display=e.dataset.h||"",this.#o(),this.#r(),this.#h()})}),this.querySelectorAll(".fp-editable").forEach(t=>{let e=t;e.addEventListener("blur",()=>{let s=e.dataset.role;s&&e.textContent.trim()&&(this.#s[s]=e.textContent.trim())})}),this.querySelector(".fp-copy-css")?.addEventListener("click",t=>{w(this.#a(),{button:t.target,announceMessage:"CSS copied"})}),this.querySelector(".fp-copy-import")?.addEventListener("click",t=>{w(this.#n(),{button:t.target,announceMessage:"@import statement copied"})})}#c(){let t=this.querySelector(".fp-preview");if(!t)return;let e={heading:`'${this.#t.heading}', serif`,body:`'${this.#t.body}', sans-serif`,code:`'${this.#t.code}', monospace`,display:`'${this.#t.display}', serif`};t.innerHTML=zt[this.#e]?.render(e,this.#s)||"",t.querySelectorAll(".fp-editable").forEach(s=>{let o=s;o.addEventListener("blur",()=>{let n=o.dataset.role;n&&o.textContent.trim()&&(this.#s[n]=o.textContent.trim())})})}#p(){this.#c(),this.#d()}#d(){let t=this.querySelector(".fp-css-output");t&&(t.textContent=this.#a())}#h(){this.dispatchEvent(new CustomEvent("font-pairer:change",{bubbles:!0,detail:{...this.#t}}))}};f("font-pairer",St);function ne(r,{type:t="linear",angle:e=90,interpolation:s="oklab"}={}){if(r.length<2)return"transparent";let n=[...r].sort((a,l)=>a.position-l.position).map(a=>`${a.color} ${a.position}%`).join(", "),i=s!=="srgb"?` in ${s}`:"";return t==="radial"?`radial-gradient(circle${i}, ${n})`:`linear-gradient(${e}deg${i}, ${n})`}function Ct(r){if(!r)return oe();let t=r.split(",").map(e=>e.trim()).filter(Boolean);return t.length<2?oe():t.map((e,s)=>({color:e,position:Math.round(s/(t.length-1)*100)}))}function oe(){return[{color:"#6366f1",position:0},{color:"#ec4899",position:100}]}var At=class extends m{static observedAttributes=["colors","type","angle","interpolation","show-export","show-controls"];#t=[];#e="linear";#s=90;#r="oklab";setup(){return this.#t=Ct(this.getAttribute("colors")??""),this.#e=this.getAttribute("type")||"linear",this.#s=Number(this.getAttribute("angle"))||90,this.#r=this.getAttribute("interpolation")||"oklab",this.#o(),!0}attributeChangedCallback(t,e,s){e===s||!this.isConnected||(t==="colors"&&(this.#t=Ct(s)),t==="type"&&(this.#e=s||"linear"),t==="angle"&&(this.#s=Number(s)||90),t==="interpolation"&&(this.#r=s||"oklab"),this.#o())}get css(){return ne(this.#t,{type:this.#e,angle:this.#s,interpolation:this.#r})}#o(){let t=this.hasAttribute("show-export"),e=this.getAttribute("show-controls")!=="false",s=this.css,o="var(--size-m, 1rem)",n="var(--size-s, 0.75rem)",i="var(--size-xs, 0.5rem)",a="var(--radius-m, 0.5rem)",l="var(--color-border, #ddd)",c="var(--color-surface, #fff)",p="var(--color-text-muted, #666)",u="var(--font-mono, monospace)",d="var(--font-size-
|
|
359
|
+
`)}#l(){this.querySelectorAll(".fp-select").forEach(t=>{t.addEventListener("change",e=>{let s=e.target;this.#t[s.dataset.role]=s.value,this.#r(),this.#c(),this.#d(),this.#h()})}),this.querySelectorAll(".fp-tab").forEach(t=>{t.addEventListener("click",()=>{let e=t;this.#e=e.dataset.mode||"combined",this.#o(),this.#r()})}),this.querySelectorAll(".fp-suggestion").forEach(t=>{t.addEventListener("click",()=>{let e=t;this.#t.heading=e.dataset.h||"",this.#t.body=e.dataset.b||"",this.#t.display=e.dataset.h||"",this.#o(),this.#r(),this.#h()})}),this.querySelectorAll(".fp-editable").forEach(t=>{let e=t;e.addEventListener("blur",()=>{let s=e.dataset.role;s&&e.textContent.trim()&&(this.#s[s]=e.textContent.trim())})}),this.querySelector(".fp-copy-css")?.addEventListener("click",t=>{w(this.#a(),{button:t.target,announceMessage:"CSS copied"})}),this.querySelector(".fp-copy-import")?.addEventListener("click",t=>{w(this.#n(),{button:t.target,announceMessage:"@import statement copied"})})}#c(){let t=this.querySelector(".fp-preview");if(!t)return;let e={heading:`'${this.#t.heading}', serif`,body:`'${this.#t.body}', sans-serif`,code:`'${this.#t.code}', monospace`,display:`'${this.#t.display}', serif`};t.innerHTML=zt[this.#e]?.render(e,this.#s)||"",t.querySelectorAll(".fp-editable").forEach(s=>{let o=s;o.addEventListener("blur",()=>{let n=o.dataset.role;n&&o.textContent.trim()&&(this.#s[n]=o.textContent.trim())})})}#p(){this.#c(),this.#d()}#d(){let t=this.querySelector(".fp-css-output");t&&(t.textContent=this.#a())}#h(){this.dispatchEvent(new CustomEvent("font-pairer:change",{bubbles:!0,detail:{...this.#t}}))}};f("font-pairer",St);function ne(r,{type:t="linear",angle:e=90,interpolation:s="oklab"}={}){if(r.length<2)return"transparent";let n=[...r].sort((a,l)=>a.position-l.position).map(a=>`${a.color} ${a.position}%`).join(", "),i=s!=="srgb"?` in ${s}`:"";return t==="radial"?`radial-gradient(circle${i}, ${n})`:`linear-gradient(${e}deg${i}, ${n})`}function Ct(r){if(!r)return oe();let t=r.split(",").map(e=>e.trim()).filter(Boolean);return t.length<2?oe():t.map((e,s)=>({color:e,position:Math.round(s/(t.length-1)*100)}))}function oe(){return[{color:"#6366f1",position:0},{color:"#ec4899",position:100}]}var At=class extends m{static observedAttributes=["colors","type","angle","interpolation","show-export","show-controls"];#t=[];#e="linear";#s=90;#r="oklab";setup(){return this.#t=Ct(this.getAttribute("colors")??""),this.#e=this.getAttribute("type")||"linear",this.#s=Number(this.getAttribute("angle"))||90,this.#r=this.getAttribute("interpolation")||"oklab",this.#o(),!0}attributeChangedCallback(t,e,s){e===s||!this.isConnected||(t==="colors"&&(this.#t=Ct(s)),t==="type"&&(this.#e=s||"linear"),t==="angle"&&(this.#s=Number(s)||90),t==="interpolation"&&(this.#r=s||"oklab"),this.#o())}get css(){return ne(this.#t,{type:this.#e,angle:this.#s,interpolation:this.#r})}#o(){let t=this.hasAttribute("show-export"),e=this.getAttribute("show-controls")!=="false",s=this.css,o="var(--size-m, 1rem)",n="var(--size-s, 0.75rem)",i="var(--size-xs, 0.5rem)",a="var(--radius-m, 0.5rem)",l="var(--color-border, #ddd)",c="var(--color-surface, #fff)",p="var(--color-text-muted, #666)",u="var(--font-mono, monospace)",d="var(--font-size-s, 0.875rem)",y="var(--font-size-xs, 0.75rem)",v=`<div class="gb-preview" style="height:4rem;border-radius:${a};background:${s};border:1px solid ${l}"></div>`,b=`font:inherit;font-size:${d};padding:0.25rem 0.5rem;border:1px solid ${l};border-radius:4px;background:${c}`,h="";e&&(h=`<div style="display:flex;flex-direction:column;gap:${n};font-size:${d}">
|
|
360
360
|
<div style="display:flex;flex-wrap:wrap;gap:${o};align-items:center">
|
|
361
361
|
<label style="display:flex;align-items:center;gap:${i}">
|
|
362
362
|
Type
|
|
@@ -448,9 +448,9 @@ ${o}
|
|
|
448
448
|
<div style="${n};margin-block-start:var(--size-s,0.5rem)">
|
|
449
449
|
<button type="button" class="ti-reset" style="${e}">Reset preview scope</button>
|
|
450
450
|
</div>
|
|
451
|
-
`,this.#s()}#s(){let t=this.querySelector(".ti-target");if(!t)return;let e=this.getAttribute("target")||"#preview",s=this.#t();t.textContent=s?`Target: ${e}`:`Target ${e} not found`}#r(){for(let n of this.querySelectorAll(".ti-mode"))this.listen(n,"click",()=>this.#o(n.dataset.mode||"paste"));let t=this.querySelector(".ti-apply-paste");t&&this.listen(t,"click",()=>this.#i());let e=this.querySelector(".ti-file");e&&this.listen(e,"change",()=>this.#a(e));let s=this.querySelector(".ti-apply-url");s&&this.listen(s,"click",()=>this.#n());let o=this.querySelector(".ti-reset");o&&this.listen(o,"click",()=>this.#c())}#o(t){for(let e of this.querySelectorAll(".ti-mode")){let s=e,o=s.dataset.mode===t;s.setAttribute("aria-selected",String(o))}for(let e of this.querySelectorAll(".ti-pane")){let s=e;s.hidden=!s.classList.contains(`ti-pane-${t}`)}}#i(){let t=this.querySelector(".ti-paste");t&&this.#l(t.value,"paste")}async#a(t){let e=t.files?.[0];if(e)try{let s=await e.text();this.#l(s,"file")}catch(s){this.#d(s,"file")}}async#n(){let e=this.querySelector(".ti-url")?.value?.trim();if(e)try{let s=await fetch(e,{mode:"cors"});if(!s.ok)throw new Error(`Fetch failed: ${s.status} ${s.statusText}`);let o=await s.text();this.#l(o,"url")}catch(s){this.#d(s,"url")}}#l(t,e){let s;try{s=JSON.parse(t)}catch(i){this.#d(i,"parse");return}let o=J(s),n=this.#t();if(!n){this.#d(new Error(`Target ${this.getAttribute("target")||"#preview"} not found`),"apply");return}for(let[i,a]of o.tokens)n.style.setProperty(i,a);this.#p(o,e),this.dispatchEvent(new CustomEvent("theme-import:applied",{bubbles:!0,detail:{tokens:o.tokens,applied:o.stats.applied,ignored:o.ignored,source:e}}))}#c(){let t=this.#t();if(!t)return;let e=t.style,s=[];for(let i=0;i<e.length;i++){let a=e.item(i);a.startsWith("--")&&s.push(a)}for(let i of s)e.removeProperty(i);let o=this.querySelector(".ti-result");o&&(o.textContent=`Cleared ${s.length} custom properties from ${this.getAttribute("target")||"#preview"}.`);let n=this.querySelector(".ti-ignored");n&&(n.hidden=!0)}#p(t,e){let s=this.querySelector(".ti-result");s&&(s.textContent=`Applied ${t.stats.applied} token${t.stats.applied===1?"":"s"} from ${e}${t.stats.ignored?` \xB7 ${t.stats.ignored} ignored`:""}.`);let o=this.querySelector(".ti-ignored"),n=this.querySelector(".ti-ignored-list");if(o&&n){let i=o;t.ignored.length===0?(i.hidden=!0,n.innerHTML=""):(i.hidden=!1,n.innerHTML=t.ignored.map(a=>`<li>${$s(a)}</li>`).join(""))}}#d(t,e){let s=this.querySelector(".ti-result");s&&(s.textContent=`Error (${e}): ${t&&t.message?t.message:String(t)}`),this.dispatchEvent(new CustomEvent("theme-import:error",{bubbles:!0,detail:{error:t,phase:e}}))}};function $s(r){return String(r).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}f("theme-import",Tt);var Mt=class extends m{static observedAttributes=["target","catalog-base"];#t=null;#e="";setup(){this.#o(),this.#a()}attributeChangedCallback(){this.isConnected&&this.hasAttribute("data-upgraded")&&(this.#o(),this.#a())}#s(){let t=this.getAttribute("target")||"#preview";try{return document.querySelector(t)}catch{return null}}#r(){let t=this.getAttribute("catalog-base");return t?t.replace(/\/$/,""):typeof window<"u"&&window.__VB_CATALOG_BASE?String(window.__VB_CATALOG_BASE).replace(/\/$/,""):"/cdn/themes/catalog"}#o(){let t="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem);min-block-size:0",e="display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--size-s,0.75rem)",s="font-size:var(--font-size-xs,0.75rem);color:var(--color-text-muted,#666)",o="margin:0;font-size:var(--font-size-
|
|
451
|
+
`,this.#s()}#s(){let t=this.querySelector(".ti-target");if(!t)return;let e=this.getAttribute("target")||"#preview",s=this.#t();t.textContent=s?`Target: ${e}`:`Target ${e} not found`}#r(){for(let n of this.querySelectorAll(".ti-mode"))this.listen(n,"click",()=>this.#o(n.dataset.mode||"paste"));let t=this.querySelector(".ti-apply-paste");t&&this.listen(t,"click",()=>this.#i());let e=this.querySelector(".ti-file");e&&this.listen(e,"change",()=>this.#a(e));let s=this.querySelector(".ti-apply-url");s&&this.listen(s,"click",()=>this.#n());let o=this.querySelector(".ti-reset");o&&this.listen(o,"click",()=>this.#c())}#o(t){for(let e of this.querySelectorAll(".ti-mode")){let s=e,o=s.dataset.mode===t;s.setAttribute("aria-selected",String(o))}for(let e of this.querySelectorAll(".ti-pane")){let s=e;s.hidden=!s.classList.contains(`ti-pane-${t}`)}}#i(){let t=this.querySelector(".ti-paste");t&&this.#l(t.value,"paste")}async#a(t){let e=t.files?.[0];if(e)try{let s=await e.text();this.#l(s,"file")}catch(s){this.#d(s,"file")}}async#n(){let e=this.querySelector(".ti-url")?.value?.trim();if(e)try{let s=await fetch(e,{mode:"cors"});if(!s.ok)throw new Error(`Fetch failed: ${s.status} ${s.statusText}`);let o=await s.text();this.#l(o,"url")}catch(s){this.#d(s,"url")}}#l(t,e){let s;try{s=JSON.parse(t)}catch(i){this.#d(i,"parse");return}let o=J(s),n=this.#t();if(!n){this.#d(new Error(`Target ${this.getAttribute("target")||"#preview"} not found`),"apply");return}for(let[i,a]of o.tokens)n.style.setProperty(i,a);this.#p(o,e),this.dispatchEvent(new CustomEvent("theme-import:applied",{bubbles:!0,detail:{tokens:o.tokens,applied:o.stats.applied,ignored:o.ignored,source:e}}))}#c(){let t=this.#t();if(!t)return;let e=t.style,s=[];for(let i=0;i<e.length;i++){let a=e.item(i);a.startsWith("--")&&s.push(a)}for(let i of s)e.removeProperty(i);let o=this.querySelector(".ti-result");o&&(o.textContent=`Cleared ${s.length} custom properties from ${this.getAttribute("target")||"#preview"}.`);let n=this.querySelector(".ti-ignored");n&&(n.hidden=!0)}#p(t,e){let s=this.querySelector(".ti-result");s&&(s.textContent=`Applied ${t.stats.applied} token${t.stats.applied===1?"":"s"} from ${e}${t.stats.ignored?` \xB7 ${t.stats.ignored} ignored`:""}.`);let o=this.querySelector(".ti-ignored"),n=this.querySelector(".ti-ignored-list");if(o&&n){let i=o;t.ignored.length===0?(i.hidden=!0,n.innerHTML=""):(i.hidden=!1,n.innerHTML=t.ignored.map(a=>`<li>${$s(a)}</li>`).join(""))}}#d(t,e){let s=this.querySelector(".ti-result");s&&(s.textContent=`Error (${e}): ${t&&t.message?t.message:String(t)}`),this.dispatchEvent(new CustomEvent("theme-import:error",{bubbles:!0,detail:{error:t,phase:e}}))}};function $s(r){return String(r).replace(/[&<>"']/g,t=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[t])}f("theme-import",Tt);var Mt=class extends m{static observedAttributes=["target","catalog-base"];#t=null;#e="";setup(){this.#o(),this.#a()}attributeChangedCallback(){this.isConnected&&this.hasAttribute("data-upgraded")&&(this.#o(),this.#a())}#s(){let t=this.getAttribute("target")||"#preview";try{return document.querySelector(t)}catch{return null}}#r(){let t=this.getAttribute("catalog-base");return t?t.replace(/\/$/,""):typeof window<"u"&&window.__VB_CATALOG_BASE?String(window.__VB_CATALOG_BASE).replace(/\/$/,""):"/cdn/themes/catalog"}#o(){let t="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem);min-block-size:0",e="display:grid;grid-template-columns:repeat(auto-fill,minmax(14rem,1fr));gap:var(--size-s,0.75rem)",s="font-size:var(--font-size-xs,0.75rem);color:var(--color-text-muted,#666)",o="margin:0;font-size:var(--font-size-m,1rem);font-weight:600;color:var(--color-text,#222)",n="align-self:flex-start;padding:0.375rem 0.75rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-primary,#0066cc);color:var(--color-text-on-primary,#fff);cursor:pointer;font:inherit;font-size:var(--font-size-xs,0.75rem)",i=`display:inline-block;padding:0.125rem 0.375rem;border-radius:0.25rem;background:var(--color-surface-raised,#f3f3f3);${s};margin-inline-end:0.25rem`;this.innerHTML=`
|
|
452
452
|
<div class="tc-head" style="display:flex;align-items:baseline;gap:var(--size-s,0.75rem);margin-block-end:var(--size-s,0.75rem);flex-wrap:wrap">
|
|
453
|
-
<strong style="font-size:var(--font-size-
|
|
453
|
+
<strong style="font-size:var(--font-size-s,0.875rem)">Start from a known system</strong>
|
|
454
454
|
<span class="tc-target" style="${s}"></span>
|
|
455
455
|
</div>
|
|
456
456
|
<div class="tc-grid" style="${e}" role="list"></div>
|
|
@@ -466,7 +466,7 @@ ${o}
|
|
|
466
466
|
:host ._btn { ${n} }
|
|
467
467
|
:host ._tag { ${i} }
|
|
468
468
|
</style>
|
|
469
|
-
`,this.#i()}#i(){let t=this.querySelector(".tc-target");if(!t)return;let e=this.getAttribute("target")||"#preview",s=this.#s();t.textContent=s?`Target: ${e}`:`Target ${e} not found`}async#a(){let t=this.querySelector(".tc-grid");if(t)try{let e=await fetch(`${this.#r()}/manifest.json`);if(!e.ok)throw new Error(`Catalog manifest fetch failed: ${e.status}`);let s=await e.json();this.#t=s.entries||[],this.#n()}catch(e){t.innerHTML="";let s=this.querySelector(".tc-result");s&&(s.textContent=`Couldn't load catalog manifest: ${e&&e.message?e.message:String(e)}`)}}#n(){let t=this.querySelector(".tc-grid");if(!t||!this.#t)return;let e="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem)",s="margin:0;font-size:var(--font-size-
|
|
469
|
+
`,this.#i()}#i(){let t=this.querySelector(".tc-target");if(!t)return;let e=this.getAttribute("target")||"#preview",s=this.#s();t.textContent=s?`Target: ${e}`:`Target ${e} not found`}async#a(){let t=this.querySelector(".tc-grid");if(t)try{let e=await fetch(`${this.#r()}/manifest.json`);if(!e.ok)throw new Error(`Catalog manifest fetch failed: ${e.status}`);let s=await e.json();this.#t=s.entries||[],this.#n()}catch(e){t.innerHTML="";let s=this.querySelector(".tc-result");s&&(s.textContent=`Couldn't load catalog manifest: ${e&&e.message?e.message:String(e)}`)}}#n(){let t=this.querySelector(".tc-grid");if(!t||!this.#t)return;let e="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);background:var(--color-surface,#fff);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-2xs,0.375rem)",s="margin:0;font-size:var(--font-size-m,1rem);font-weight:600;color:var(--color-text,#222)",o="align-self:flex-start;margin-block-start:auto;padding:0.375rem 0.75rem;border:1px solid var(--color-border,#ccc);border-radius:var(--radius-s,0.25rem);background:var(--color-primary,#0066cc);color:var(--color-text-on-primary,#fff);cursor:pointer;font:inherit;font-size:var(--font-size-xs,0.75rem)",n="font-size:var(--font-size-xs,0.75rem);color:var(--color-text-muted,#666)",i=`display:inline-block;padding:0.125rem 0.375rem;border-radius:0.25rem;background:var(--color-surface-raised,#f3f3f3);${n};margin-inline-end:0.25rem`;t.innerHTML="";for(let a of this.#t){let l=document.createElement("article");l.setAttribute("role","listitem"),l.setAttribute("data-id",a.id),l.style.cssText=e,l.innerHTML=`
|
|
470
470
|
<h3 style="${s}">${O(a.name)}</h3>
|
|
471
471
|
<p style="${n};margin:0">${O(a.summary||"")}</p>
|
|
472
472
|
<p style="${n};margin:0">License: ${O(a.license)}</p>
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@profpowell/vb-design-system",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Design-system documentation components for Vanilla Breeze:
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Design-system documentation components for Vanilla Breeze: type, spacing, token, motion, layout, breakpoint, accessibility, icon and brand specimens; color palette, semantic palette, palette generator, gradient builder, font pairer; component sampler; theme catalog, export and import.",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"author": "
|
|
6
|
+
"author": "Thomas A. Powell",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"homepage": "https://github.com/ProfPowell/vb-design-system#readme",
|
|
9
9
|
"repository": {
|
|
@@ -64,7 +64,7 @@
|
|
|
64
64
|
"test:components": "playwright test"
|
|
65
65
|
},
|
|
66
66
|
"peerDependencies": {
|
|
67
|
-
"vanilla-breeze": ">=0.
|
|
67
|
+
"vanilla-breeze": ">=0.4.0"
|
|
68
68
|
},
|
|
69
69
|
"peerDependenciesMeta": {
|
|
70
70
|
"vanilla-breeze": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
74
|
"devDependencies": {
|
|
75
|
-
"@playwright/test": "^1.
|
|
76
|
-
"esbuild": "^0.
|
|
75
|
+
"@playwright/test": "^1.64.1",
|
|
76
|
+
"esbuild": "^0.28.2"
|
|
77
77
|
}
|
|
78
78
|
}
|
package/src/lib/vb-element.js
CHANGED
|
@@ -2,10 +2,21 @@
|
|
|
2
2
|
* VBElement — Minimal base class for Vanilla Breeze web components
|
|
3
3
|
*
|
|
4
4
|
* Provides:
|
|
5
|
-
* - data-upgraded guard (
|
|
5
|
+
* - data-upgraded guard (dedupes back-to-back connectedCallbacks with no
|
|
6
|
+
* disconnect between them — NOT a reconnect guard, see the lifecycle note)
|
|
6
7
|
* - listen() method with automatic cleanup on disconnect
|
|
7
8
|
* - setup()/teardown() lifecycle hooks
|
|
8
9
|
*
|
|
10
|
+
* Lifecycle on move / reconnect: disconnectedCallback runs teardown() and
|
|
11
|
+
* REMOVES data-upgraded, so the next connectedCallback runs setup() again.
|
|
12
|
+
* That means setup() must be idempotent across a disconnect+reconnect: the
|
|
13
|
+
* data-upgraded flag only suppresses a *repeated* connect while the element is
|
|
14
|
+
* still connected, it does not survive a disconnect. A setup() that builds DOM
|
|
15
|
+
* without either a teardown() that removes it or an "already built" guard will
|
|
16
|
+
* duplicate that DOM every time the element is moved. The house patterns are
|
|
17
|
+
* star-rating's `if (this.querySelector(...)) return` and the
|
|
18
|
+
* `node?.parentNode === this` early return.
|
|
19
|
+
*
|
|
9
20
|
* Does NOT provide: props reflection, template rendering, reactivity.
|
|
10
21
|
* Components that need observedAttributes/attributeChangedCallback
|
|
11
22
|
* declare them normally alongside setup()/teardown().
|
|
@@ -16,6 +27,9 @@ class VBElement extends HTMLElement {
|
|
|
16
27
|
#internals;
|
|
17
28
|
|
|
18
29
|
connectedCallback() {
|
|
30
|
+
// Suppresses a repeated connect while still connected. It does NOT survive
|
|
31
|
+
// disconnect (see disconnectedCallback), so setup() still re-runs on every
|
|
32
|
+
// reconnect — see the class-level lifecycle note.
|
|
19
33
|
if (this.hasAttribute('data-upgraded')) return;
|
|
20
34
|
if (this.setup() === false) return;
|
|
21
35
|
this.setAttribute('data-upgraded', '');
|
|
@@ -36,7 +36,7 @@ breakpoint-specimen {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
.bps-active {
|
|
39
|
-
font-size: var(--font-size-
|
|
39
|
+
font-size: var(--font-size-s, 0.875rem);
|
|
40
40
|
padding: var(--size-3xs, 0.125rem) var(--size-xs, 0.5rem);
|
|
41
41
|
border-radius: var(--radius-s, 0.25rem);
|
|
42
42
|
background: var(--color-surface-raised, oklch(96% 0 0));
|
|
@@ -111,7 +111,7 @@ breakpoint-specimen {
|
|
|
111
111
|
grid-template-columns: max-content 1fr;
|
|
112
112
|
gap: var(--size-2xs, 0.25rem) var(--size-m, 1rem);
|
|
113
113
|
margin: 0;
|
|
114
|
-
font-size: var(--font-size-
|
|
114
|
+
font-size: var(--font-size-s, 0.875rem);
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
.bps-row {
|
|
@@ -34,11 +34,11 @@ const PREVIEWS = {
|
|
|
34
34
|
render: (f, t) => `
|
|
35
35
|
<p style="font-family:${f.display};font-size:var(--font-size-3xl,2rem);font-weight:800;margin:0;line-height:1.15"
|
|
36
36
|
${E(f.display,'p','heading')}>${t.heading}</p>
|
|
37
|
-
<h3 style="font-family:${f.heading};font-size:var(--font-size-
|
|
37
|
+
<h3 style="font-family:${f.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0"
|
|
38
38
|
${E(f.heading,'h3','subheading')}>${t.subheading}</h3>
|
|
39
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
39
|
+
<p style="font-family:${f.body};font-size:var(--font-size-m,1rem);line-height:1.65;margin:0;color:var(--color-text-muted,#666)"
|
|
40
40
|
${E(f.body,'p','body')}>${t.body}</p>
|
|
41
|
-
<pre style="font-family:${f.code};font-size:var(--font-size-
|
|
41
|
+
<pre style="font-family:${f.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code ${E(f.code,'code','code')}>${t.code}</code></pre>`,
|
|
42
42
|
},
|
|
43
43
|
article: {
|
|
44
44
|
label: 'Article',
|
|
@@ -47,31 +47,31 @@ const PREVIEWS = {
|
|
|
47
47
|
${E(f.body,'small','eyebrow')}>${t.eyebrow}</small>
|
|
48
48
|
<h2 style="font-family:${f.heading};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0;line-height:1.2"
|
|
49
49
|
${E(f.heading,'h2','heading')}>${t.heading}</h2>
|
|
50
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
50
|
+
<p style="font-family:${f.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0"
|
|
51
51
|
${E(f.body,'p','byline')}>${t.byline}</p>
|
|
52
52
|
<p style="font-family:${f.body};line-height:1.7;margin:0" ${E(f.body,'p','body')}>${t.body}</p>
|
|
53
|
-
<h3 style="font-family:${f.heading};font-size:var(--font-size-
|
|
53
|
+
<h3 style="font-family:${f.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0"
|
|
54
54
|
${E(f.heading,'h3','subheading')}>${t.subheading}</h3>
|
|
55
55
|
<p style="font-family:${f.body};line-height:1.7;margin:0" ${E(f.body,'p','body2')}>${t.body2}</p>
|
|
56
|
-
<blockquote style="font-family:${f.display};font-style:italic;font-size:var(--font-size-
|
|
56
|
+
<blockquote style="font-family:${f.display};font-style:italic;font-size:var(--font-size-l,1.125rem);border-inline-start:3px solid var(--color-interactive,oklch(55% .2 260));padding-inline-start:var(--size-m,1rem);margin:0;color:var(--color-text-muted,#666)"
|
|
57
57
|
${E(f.display,'blockquote','quote')}>${t.quote}</blockquote>
|
|
58
|
-
<pre style="font-family:${f.code};font-size:var(--font-size-
|
|
58
|
+
<pre style="font-family:${f.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code ${E(f.code,'code','code')}>${t.code}</code></pre>`,
|
|
59
59
|
},
|
|
60
60
|
'long-article': {
|
|
61
61
|
label: 'Long Article',
|
|
62
62
|
render: (f, t) => `
|
|
63
63
|
<small style="font-family:${f.body};font-size:var(--font-size-xs,0.75rem);text-transform:uppercase;letter-spacing:0.08em;color:var(--color-interactive,oklch(55% .2 260));font-weight:600">${t.eyebrow}</small>
|
|
64
64
|
<h1 style="font-family:${f.display};font-size:var(--font-size-3xl,2rem);font-weight:800;margin:0;line-height:1.15">${t.heading}</h1>
|
|
65
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
66
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
65
|
+
<p style="font-family:${f.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0">${t.byline}</p>
|
|
66
|
+
<p style="font-family:${f.body};font-size:var(--font-size-l,1.125rem);line-height:1.6;margin:0;color:var(--color-text-muted,#666)">${t.lead}</p>
|
|
67
67
|
<h2 style="font-family:${f.heading};font-size:var(--font-size-xl,1.375rem);font-weight:700;margin:0">${t.subheading}</h2>
|
|
68
68
|
<p style="font-family:${f.body};line-height:1.7;margin:0">${t.body}</p>
|
|
69
69
|
<p style="font-family:${f.body};line-height:1.7;margin:0">${t.body2}</p>
|
|
70
|
-
<blockquote style="font-family:${f.display};font-style:italic;font-size:var(--font-size-
|
|
70
|
+
<blockquote style="font-family:${f.display};font-style:italic;font-size:var(--font-size-l,1.125rem);border-inline-start:3px solid var(--color-interactive,oklch(55% .2 260));padding-inline-start:var(--size-m,1rem);margin:0;color:var(--color-text-muted,#666)">${t.quote}</blockquote>
|
|
71
71
|
<h2 style="font-family:${f.heading};font-size:var(--font-size-xl,1.375rem);font-weight:700;margin:0">Implementation Details</h2>
|
|
72
72
|
<p style="font-family:${f.body};line-height:1.7;margin:0">Design tokens form the atomic layer of any visual system. Colors, spacing, typography, and motion are expressed as named variables that cascade through every component. When a token changes, every surface that references it updates automatically — no find-and-replace, no missed instances.</p>
|
|
73
|
-
<pre style="font-family:${f.code};font-size:var(--font-size-
|
|
74
|
-
<h3 style="font-family:${f.heading};font-size:var(--font-size-
|
|
73
|
+
<pre style="font-family:${f.code};font-size:var(--font-size-s,0.875rem);line-height:1.5;margin:0;padding:var(--size-s,0.75rem);background:var(--color-surface-sunken,#eee);border-radius:var(--radius-s,0.25rem);overflow-x:auto"><code>${t.code}</code></pre>
|
|
74
|
+
<h3 style="font-family:${f.heading};font-size:var(--font-size-l,1.125rem);font-weight:600;margin:0">Key Takeaways</h3>
|
|
75
75
|
<ul style="font-family:${f.body};line-height:1.7;margin:0;padding-inline-start:1.5rem">
|
|
76
76
|
<li>Typography sets the emotional tone before a single word is read</li>
|
|
77
77
|
<li>Pair contrast with harmony — serif headings with sans-serif body</li>
|
|
@@ -86,13 +86,13 @@ const PREVIEWS = {
|
|
|
86
86
|
<div style="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-xs,0.5rem)">
|
|
87
87
|
<h4 style="font-family:${f.heading};font-weight:600;margin:0" ${E(f.heading,'h4','cardTitle')}>Premium Plan</h4>
|
|
88
88
|
<p style="font-family:${f.display};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0">$49<small style="font-size:0.5em;font-weight:400">/mo</small></p>
|
|
89
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
89
|
+
<p style="font-family:${f.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0" ${E(f.body,'p','cardBody')}>Everything you need to build faster.</p>
|
|
90
90
|
<code style="font-family:${f.code};font-size:var(--font-size-xs,0.75rem);background:var(--color-surface-sunken,#eee);padding:0.2rem 0.4rem;border-radius:0.25rem" ${E(f.code,'code','cardCode')}>npm install acme</code>
|
|
91
91
|
</div>
|
|
92
92
|
<div style="border:1px solid var(--color-border,#ddd);border-radius:var(--radius-m,0.5rem);padding:var(--size-m,1rem);display:flex;flex-direction:column;gap:var(--size-xs,0.5rem)">
|
|
93
93
|
<h4 style="font-family:${f.heading};font-weight:600;margin:0">Enterprise</h4>
|
|
94
94
|
<p style="font-family:${f.display};font-size:var(--font-size-2xl,1.75rem);font-weight:700;margin:0">Custom</p>
|
|
95
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
95
|
+
<p style="font-family:${f.body};font-size:var(--font-size-s,0.875rem);color:var(--color-text-muted,#666);margin:0">Dedicated support and SLA guarantees.</p>
|
|
96
96
|
<code style="font-family:${f.code};font-size:var(--font-size-xs,0.75rem);background:var(--color-surface-sunken,#eee);padding:0.2rem 0.4rem;border-radius:0.25rem">contact@acme.dev</code>
|
|
97
97
|
</div>
|
|
98
98
|
</div>`,
|
|
@@ -105,7 +105,7 @@ const PREVIEWS = {
|
|
|
105
105
|
${E(f.body,'p','eyebrow')}>${t.eyebrow}</p>
|
|
106
106
|
<h1 style="font-family:${f.display};font-size:clamp(2rem,5vw,3rem);font-weight:800;margin:0;line-height:1.1"
|
|
107
107
|
${E(f.display,'h1','heading')}>${t.heading}</h1>
|
|
108
|
-
<p style="font-family:${f.body};font-size:var(--font-size-
|
|
108
|
+
<p style="font-family:${f.body};font-size:var(--font-size-l,1.125rem);color:var(--color-text-muted,#666);margin:var(--size-s,0.75rem) auto 0;max-width:40ch"
|
|
109
109
|
${E(f.body,'p','body')}>${t.body}</p>
|
|
110
110
|
</div>`,
|
|
111
111
|
},
|
|
@@ -170,7 +170,7 @@ class FontPairer extends VBElement {
|
|
|
170
170
|
const surface = 'var(--color-surface, #fff)';
|
|
171
171
|
const raised = 'var(--color-surface-raised, #f5f5f5)';
|
|
172
172
|
const muted = 'var(--color-text-muted, #666)';
|
|
173
|
-
const smFont = 'var(--font-size-
|
|
173
|
+
const smFont = 'var(--font-size-s, 0.875rem)';
|
|
174
174
|
const xsFont = 'var(--font-size-xs, 0.75rem)';
|
|
175
175
|
const selectStyle = `font:inherit;font-size:${smFont};padding:0.35rem 0.5rem;border:1px solid ${border};border-radius:4px;background:${surface}`;
|
|
176
176
|
|
|
@@ -70,7 +70,7 @@ class GradientBuilder extends VBElement {
|
|
|
70
70
|
const surface = 'var(--color-surface, #fff)';
|
|
71
71
|
const muted = 'var(--color-text-muted, #666)';
|
|
72
72
|
const mono = 'var(--font-mono, monospace)';
|
|
73
|
-
const smFont = 'var(--font-size-
|
|
73
|
+
const smFont = 'var(--font-size-s, 0.875rem)';
|
|
74
74
|
const xsFont = 'var(--font-size-xs, 0.75rem)';
|
|
75
75
|
|
|
76
76
|
// Preview strip
|
|
@@ -84,7 +84,7 @@ class MotionSpecimen extends VBElement {
|
|
|
84
84
|
}
|
|
85
85
|
|
|
86
86
|
#nameStyle() {
|
|
87
|
-
return `font-family:${MONO};font-size:var(--font-size-
|
|
87
|
+
return `font-family:${MONO};font-size:var(--font-size-s,0.875rem);color:${MUTED};text-align:end`;
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
#valueStyle() {
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Uses hue rotation in HSL space — same principle as the OKLCH harmonics
|
|
5
5
|
* in color-mix.css but computed in JS for dynamic generation.
|
|
6
6
|
*/
|
|
7
|
-
import { hexToHsl, hslToHex } from '
|
|
7
|
+
import { hexToHsl, hslToHex } from '../../lib/color-utils.js';
|
|
8
8
|
|
|
9
9
|
/** Wrap hue to 0-360 range */
|
|
10
10
|
const wrap = (h) => ((h % 360) + 360) % 360;
|
|
@@ -29,7 +29,7 @@ import { registerComponent } from '../../lib/bundle-registry.js';
|
|
|
29
29
|
import { VBElement } from '../../lib/vb-element.js';
|
|
30
30
|
import { copyText } from '../../utils/copy-init.js';
|
|
31
31
|
import { generatePalette } from './_palette-utils.js';
|
|
32
|
-
import { hexToRgb } from '
|
|
32
|
+
import { hexToRgb } from '../../lib/color-utils.js';
|
|
33
33
|
|
|
34
34
|
class PaletteGenerator extends VBElement {
|
|
35
35
|
static observedAttributes = ['seed', 'harmony', 'include-seed', 'show-export',
|
|
@@ -9,7 +9,7 @@ palette-generator {
|
|
|
9
9
|
|
|
10
10
|
palette-generator .pg-seed-label {
|
|
11
11
|
display: block;
|
|
12
|
-
font-size: var(--font-size-
|
|
12
|
+
font-size: var(--font-size-s, 0.875rem);
|
|
13
13
|
font-weight: 600;
|
|
14
14
|
color: var(--color-text-muted, #666);
|
|
15
15
|
margin-block-end: var(--size-2xs, 0.25rem);
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* - relativeLuminance + contrastRatio: WCAG 2.1 contrast for text-vs-background.
|
|
6
6
|
* - pickContrastingHex: black-or-white pick by perceived luminance.
|
|
7
7
|
*/
|
|
8
|
-
import { hexToRgb, rgbToHex } from '
|
|
8
|
+
import { hexToRgb, rgbToHex } from '../../lib/color-utils.js';
|
|
9
9
|
|
|
10
10
|
const srgbToLinear = (c) =>
|
|
11
11
|
c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|