Spaces:
Running
Running
| class PowerButton extends HTMLElement { | |
| static get observedAttributes() { | |
| return ['active']; | |
| } | |
| constructor() { | |
| super(); | |
| this.attachShadow({ mode: 'open' }); | |
| this.active = false; | |
| this.render(); | |
| } | |
| attributeChangedCallback(name, oldValue, newValue) { | |
| if (name === 'active') { | |
| this.active = newValue === 'true'; | |
| this.updateState(); | |
| } | |
| } | |
| render() { | |
| this.shadowRoot.innerHTML = ` | |
| <style> | |
| :host { | |
| display: block; | |
| position: relative; | |
| } | |
| .button-wrapper { | |
| position: relative; | |
| width: 140px; | |
| height: 140px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| } | |
| .ripple { | |
| position: absolute; | |
| inset: 0; | |
| border-radius: 50%; | |
| border: 2px solid #06b6d4; | |
| opacity: 0; | |
| transform: scale(1); | |
| } | |
| .ripple.active { | |
| animation: ripple 2s linear infinite; | |
| } | |
| @keyframes ripple { | |
| 0% { transform: scale(1); opacity: 0.5; } | |
| 100% { transform: scale(1.5); opacity: 0; } | |
| } | |
| .button { | |
| width: 100px; | |
| height: 100px; | |
| border-radius: 50%; | |
| border: none; | |
| background: linear-gradient(145deg, #1f2937, #111827); | |
| box-shadow: | |
| 20px 20px 40px #0b0f19, | |
| -20px -20px 40px #27354f, | |
| inset 0 0 0 1px rgba(255,255,255,0.1); | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| z-index: 10; | |
| } | |
| .button:hover { | |
| transform: scale(1.05); | |
| box-shadow: | |
| 25px 25px 50px #0b0f19, | |
| -25px -25px 50px #27354f, | |
| inset 0 0 0 1px rgba(255,255,255,0.2); | |
| } | |
| .button:active { | |
| transform: scale(0.95); | |
| } | |
| .button.active { | |
| background: linear-gradient(145deg, #0891b2, #06b6d4); | |
| box-shadow: | |
| 0 0 40px rgba(6, 182, 212, 0.5), | |
| inset 0 0 20px rgba(255,255,255,0.2); | |
| } | |
| .button.active svg { | |
| color: white; | |
| filter: drop-shadow(0 0 10px rgba(255,255,255,0.8)); | |
| } | |
| .icon { | |
| width: 40px; | |
| height: 40px; | |
| color: #6b7280; | |
| transition: all 0.3s ease; | |
| } | |
| .button:hover .icon { | |
| color: #9ca3af; | |
| } | |
| .status-ring { | |
| position: absolute; | |
| inset: 10px; | |
| border-radius: 50%; | |
| border: 3px solid transparent; | |
| border-top-color: #06b6d4; | |
| opacity: 0; | |
| transition: opacity 0.3s; | |
| } | |
| .button.active + .status-ring { | |
| opacity: 1; | |
| animation: spin 1s linear infinite; | |
| } | |
| @keyframes spin { | |
| to { transform: rotate(360deg); } | |
| } | |
| </style> | |
| <div class="button-wrapper"> | |
| <div class="ripple" id="ripple1"></div> | |
| <div class="ripple" id="ripple2" style="animation-delay: 0.5s"></div> | |
| <div class="ripple" id="ripple3" style="animation-delay: 1s"></div> | |
| <button class="button" id="powerBtn"> | |
| <svg class="icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"> | |
| <path d="M18.36 6.64a9 9 0 1 1-12.73 0"></path> | |
| <line x1="12" y1="2" x2="12" y2="12"></line> | |
| </svg> | |
| </button> | |
| <div class="status-ring"></div> | |
| </div> | |
| `; | |
| this.button = this.shadowRoot.getElementById('powerBtn'); | |
| this.ripples = this.shadowRoot.querySelectorAll('.ripple'); | |
| this.button.addEventListener('click', () => { | |
| this.dispatchEvent(new CustomEvent('power-toggle', { | |
| bubbles: true, | |
| composed: true | |
| })); | |
| }); | |
| this.updateState(); | |
| } | |
| updateState() { | |
| if (!this.button) return; | |
| if (this.active) { | |
| this.button.classList.add('active'); | |
| this.ripples.forEach(r => r.classList.add('active')); | |
| } else { | |
| this.button.classList.remove('active'); | |
| this.ripples.forEach(r => r.classList.remove('active')); | |
| } | |
| } | |
| } | |
| customElements.define('power-button', PowerButton); |