UNPKG

luminomorphism

Version:

A UI design system built around light, blur, ambient motion and perceptual feedback.

41 lines (40 loc) 2.42 kB
class LPrismLayer extends HTMLElement{constructor(){super(),this.attachShadow({mode:"open"}),this.wrapper=document.createElement("div"),this.wrapper.classList.add("prism-layer"),this.wrapper.innerHTML="<slot></slot>",this.styleEl=document.createElement("style"),this.shadowRoot.append(this.styleEl,this.wrapper),this.intensity=this.getAttribute("intensity")||"medium",this.interaction=this.getAttribute("interaction")||"hover",this.mouse={x:0,y:0},this.animate=this.animate.bind(this)}connectedCallback(){this.updateStyle(),this.interaction==="cursor"&&this.addEventListener("pointermove",this.trackMouse.bind(this)),requestAnimationFrame(this.animate)}static get observedAttributes(){return["intensity","interaction"]}attributeChangedCallback(e,t,i){t!==i&&(this[e]=i,this.updateStyle())}trackMouse(e){const t=this.getBoundingClientRect();this.mouse.x=e.clientX-t.left,this.mouse.y=e.clientY-t.top}animate(){const e=this.wrapper;if(this.interaction==="cursor"){const t=this.mouse.x,i=this.mouse.y,s=this.offsetWidth/2,r=this.offsetHeight/2,n=t-s,o=i-r,a=Math.atan2(o,n)*(180/Math.PI);e.style.setProperty("--prism-angle",`${a}deg`)}requestAnimationFrame(this.animate)}updateStyle(){const t={low:"0.15",medium:"0.3",high:"0.5"}[this.intensity]||"0.3",i={hover:` .prism-layer::before { opacity: 0; transform: rotate(0deg); } .prism-layer:hover::before { opacity: ${t}; transform: rotate(25deg); } `,always:` .prism-layer::before { opacity: ${t}; transform: rotate(0deg); } `,cursor:` .prism-layer::before { opacity: ${t}; transform: rotate(var(--prism-angle, 0deg)); } `},s=i[this.interaction]||i.hover;this.styleEl.textContent=` .prism-layer { position: relative; display: inline-block; overflow: hidden; background: inherit; border-radius: 12px; } .prism-layer::before { content: ""; position: absolute; inset: 0; background: conic-gradient(from 0deg, red, orange, yellow, green, blue, indigo, violet, red); mix-blend-mode: screen; filter: blur(20px) hue-rotate(0deg); pointer-events: none; transition: opacity 0.4s ease, transform 0.4s ease; z-index: 1; } ${s} `}}customElements.define("l-prism-layer",LPrismLayer);