From 3bd5752cb5197980eadd90e3194571d66aa87012 Mon Sep 17 00:00:00 2001 From: cottongin Date: Sun, 3 May 2026 01:24:47 -0400 Subject: [PATCH] feat: enhance full-room glow with configurable controls and prevent text wrapping Add white-space: nowrap to header, footer, and code-part elements to prevent line breaks in narrow viewports. Replace static CSS keyframes with dynamic generation so glow color, intensity, opacity, outline thickness, and pulse duration are all configurable from the controls panel. Double the default outline thickness from 4px to 8px. Co-authored-by: Cursor --- js/room-code-display.js | 55 +++++++++++++++++++++++++++++++++++++++++ optimized-controls.html | 53 ++++++++++++++++++++++++++++++++------- 2 files changed, 99 insertions(+), 9 deletions(-) diff --git a/js/room-code-display.js b/js/room-code-display.js index 556391b..11e0f08 100644 --- a/js/room-code-display.js +++ b/js/room-code-display.js @@ -41,6 +41,12 @@ * @property {HTMLInputElement} line2AppearDuration * @property {HTMLInputElement} line2HideTime * @property {HTMLInputElement} line2HideDuration + * @property {HTMLInputElement} glowColor + * @property {HTMLInputElement} glowIntensity + * @property {HTMLInputElement} glowOpacity + * @property {HTMLInputElement} glowWhiteIntensity + * @property {HTMLInputElement} glowOutline + * @property {HTMLInputElement} glowPulseDuration */ class RoomCodeDisplay { @@ -65,6 +71,8 @@ class RoomCodeDisplay { /** @type {number | null} */ #meterRafId = null; + /** @type {HTMLStyleElement | null} */ + #glowStyleEl = null; /** * @param {RoomCodeDisplayElements} elements @@ -73,6 +81,12 @@ class RoomCodeDisplay { init(elements, inputs) { this.#elements = elements; this.#inputs = inputs; + + if (!this.#glowStyleEl) { + this.#glowStyleEl = document.createElement('style'); + this.#glowStyleEl.id = 'glow-keyframes'; + document.head.appendChild(this.#glowStyleEl); + } } /** @@ -217,6 +231,9 @@ class RoomCodeDisplay { footer.style.color = inputs.footerColor.value; footer.style.fontSize = `${inputs.footerSize.value}px`; footer.style.transform = `translateY(${inputs.footerOffset.value}px)`; + + this.#rebuildGlowKeyframes(); + this.#checkFullPulse(); } #startAnimation() { @@ -370,14 +387,52 @@ class RoomCodeDisplay { this.#meterRafId = requestAnimationFrame(step); } + #rebuildGlowKeyframes() { + const inputs = this.#inputs; + const style = this.#glowStyleEl; + if (!inputs || !style) return; + + const outline = Number(inputs.glowOutline?.value ?? 8); + const whiteGlow = Number(inputs.glowWhiteIntensity?.value ?? 40); + const colorGlow = Number(inputs.glowIntensity?.value ?? 80); + const opacity = Number(inputs.glowOpacity?.value ?? 0.6); + const duration = Number(inputs.glowPulseDuration?.value ?? 1.2); + + const glowHex = inputs.glowColor?.value ?? '#f35dcb'; + const r = parseInt(glowHex.slice(1, 3), 16); + const g = parseInt(glowHex.slice(3, 5), 16); + const b = parseInt(glowHex.slice(5, 7), 16); + + const outlineShadow = + `drop-shadow(0 0 ${outline}px black) drop-shadow(0 0 ${outline}px black)`; + + style.textContent = ` + @keyframes meter-full-pulse { + 0%, 100% { + filter: ${outlineShadow} drop-shadow(0 0 0 rgba(255,255,255,0)); + } + 50% { + filter: ${outlineShadow} + drop-shadow(0 0 ${whiteGlow}px rgba(255,255,255,0.95)) + drop-shadow(0 0 ${colorGlow}px rgba(${r},${g},${b},${opacity})); + } + } + #header.meter-full-pulse { + animation: meter-full-pulse ${duration}s ease-in-out infinite; + } + `; + } + #checkFullPulse() { const header = this.#elements?.header; if (!header) return; if (this.#meterFill >= 1) { + this.#rebuildGlowKeyframes(); header.classList.add('meter-full-pulse'); } else { header.classList.remove('meter-full-pulse'); + header.style.animation = ''; } } } diff --git a/optimized-controls.html b/optimized-controls.html index 8395ed5..332cc34 100644 --- a/optimized-controls.html +++ b/optimized-controls.html @@ -30,6 +30,7 @@ #header { position: absolute; width: fit-content; + white-space: nowrap; left: 50%; transform: translateX(-50%) translateY(-220px); color: #f35dcb; @@ -45,19 +46,12 @@ filter: drop-shadow(3px 3px 8px rgba(0, 0, 0, 0.8)); } - @keyframes meter-full-pulse { - 0% { filter: drop-shadow(3px 3px 8px rgba(0,0,0,0.8)); } - 50% { filter: drop-shadow(0 0 20px rgba(255,255,255,0.6)) drop-shadow(3px 3px 8px rgba(0,0,0,0.8)); } - 100% { filter: drop-shadow(3px 3px 8px rgba(0,0,0,0.8)); } - } - - #header.meter-full-pulse { - animation: meter-full-pulse 1.2s ease-in-out infinite; - } + /* meter-full-pulse keyframes are generated dynamically by RoomCodeDisplay */ #footer { position: absolute; width: 100%; + white-space: nowrap; text-align: center; transform: translateY(160px); color: #f35dcb; @@ -77,6 +71,7 @@ letter-spacing: 8px; position: absolute; width: 100%; + white-space: nowrap; text-align: center; opacity: 0; transition: opacity 0.5s ease; @@ -542,6 +537,40 @@ + +
+
+ Glow Effect Settings + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
@@ -855,6 +884,12 @@ line2AppearDuration: document.getElementById('line2-appear-duration'), line2HideTime: document.getElementById('line2-hide-time'), line2HideDuration: document.getElementById('line2-hide-duration'), + glowColor: document.getElementById('glow-color-input'), + glowIntensity: document.getElementById('glow-intensity-input'), + glowOpacity: document.getElementById('glow-opacity-input'), + glowWhiteIntensity: document.getElementById('glow-white-intensity-input'), + glowOutline: document.getElementById('glow-outline-input'), + glowPulseDuration: document.getElementById('glow-pulse-duration-input'), } ); manager.registerComponent('roomCode', roomCodeDisplay);