luminomorphism
Version:
A UI design system built around light, blur, ambient motion and perceptual feedback.
28 lines (27 loc) • 2.23 kB
JavaScript
class LFocusFlare extends HTMLElement{static get observedAttributes(){return["color","intensity","duration","radius"]}constructor(){super(),this.attachShadow({mode:"open"}),this.color=this.getAttribute("color")||"#00ffff",this.intensity=parseFloat(this.getAttribute("intensity"))||.6,this.duration=parseInt(this.getAttribute("duration"))||600,this.radius=parseInt(this.getAttribute("radius"))||60,this.flare=null}connectedCallback(){this.render();const e=this.shadowRoot.querySelector("slot");e.addEventListener("slotchange",()=>{e.assignedElements().forEach(t=>{t.addEventListener("focus",this.showFlare.bind(this)),t.addEventListener("blur",this.hideFlare.bind(this))})})}attributeChangedCallback(e,i,t){i!==t&&(e==="color"&&(this.color=t),e==="intensity"&&(this.intensity=parseFloat(t)||.6),e==="duration"&&(this.duration=parseInt(t)||600),e==="radius"&&(this.radius=parseInt(t)||60),this.render())}render(){const e=document.createElement("style");e.textContent=`
:host {
position: relative;
display: inline-block;
}
.flare {
content: '';
position: absolute;
top: 50%;
left: 50%;
width: ${this.radius*2}px;
height: ${this.radius*2}px;
margin-left: -${this.radius}px;
margin-top: -${this.radius}px;
background: radial-gradient(circle, ${this.color}${Math.floor(this.intensity*255).toString(16)}, transparent);
opacity: 0;
border-radius: 50%;
pointer-events: none;
transform: scale(0.8);
transition: opacity ${this.duration}ms ease, transform ${this.duration}ms ease;
z-index: -1;
}
.flare.visible {
opacity: ${this.intensity};
transform: scale(1);
}
`;const i=document.createElement("div");i.style.position="relative";const t=document.createElement("div");t.classList.add("flare");const s=document.createElement("slot");i.appendChild(t),i.appendChild(s),this.shadowRoot.innerHTML="",this.shadowRoot.appendChild(e),this.shadowRoot.appendChild(i),this.flare=t}showFlare(){this.flare&&this.flare.classList.add("visible")}hideFlare(){this.flare&&this.flare.classList.remove("visible")}}customElements.define("l-focus-flare",LFocusFlare);