feat: continuous pulse glow when lobby is full, add horizontal offset for player list

Make the header meter pulse animation loop indefinitely (1.2s
ease-in-out) while playerCount equals maxPlayers. Stops when a
player leaves. Also add horizontal offset control for the player
list positioning.

Made-with: Cursor
This commit is contained in:
cottongin
2026-03-20 15:15:09 -04:00
parent 4c56b7f8f9
commit 06e375ccdc
3 changed files with 14 additions and 14 deletions

View File

@@ -13,6 +13,7 @@ const DEFAULT_MAX_PLAYERS = 8;
* @property {HTMLInputElement} textColor * @property {HTMLInputElement} textColor
* @property {HTMLInputElement} emptyColor * @property {HTMLInputElement} emptyColor
* @property {HTMLInputElement} offset * @property {HTMLInputElement} offset
* @property {HTMLInputElement} offsetX
*/ */
/** /**
@@ -214,9 +215,18 @@ export class PlayerList {
const textColor = inputs.textColor.value; const textColor = inputs.textColor.value;
const emptyColor = inputs.emptyColor.value; const emptyColor = inputs.emptyColor.value;
const offsetY = `${parseInt(inputs.offset.value, 10) || 0}px`; const offsetY = `${parseInt(inputs.offset.value, 10) || 0}px`;
const offsetX = parseInt(inputs.offsetX?.value, 10) || 0;
container.style.transform = `translateY(calc(-50% + ${offsetY}))`; container.style.transform = `translateY(calc(-50% + ${offsetY}))`;
if (pos === 'right') {
container.style.right = `${24 + offsetX}px`;
container.style.left = '';
} else {
container.style.left = `${24 + offsetX}px`;
container.style.right = '';
}
for (const slot of this._slots) { for (const slot of this._slots) {
slot.nameEl.style.fontSize = fontPx; slot.nameEl.style.fontSize = fontPx;
slot.element.querySelector('.player-slot-number').style.fontSize = fontPx; slot.element.querySelector('.player-slot-number').style.fontSize = fontPx;

View File

@@ -65,8 +65,6 @@ export class RoomCodeDisplay {
/** @type {number | null} */ /** @type {number | null} */
#meterRafId = null; #meterRafId = null;
/** @type {boolean} */
#meterPulseFired = false;
/** /**
* @param {RoomCodeDisplayElements} elements * @param {RoomCodeDisplayElements} elements
@@ -107,7 +105,6 @@ export class RoomCodeDisplay {
const initialFill = max > 0 ? count / max : 0; const initialFill = max > 0 ? count / max : 0;
this.#meterFill = Math.max(0, Math.min(1, initialFill)); this.#meterFill = Math.max(0, Math.min(1, initialFill));
this.#meterTarget = this.#meterFill; this.#meterTarget = this.#meterFill;
this.#meterPulseFired = false;
this.#applyMeterGradient(); this.#applyMeterGradient();
this.#startAnimation(); this.#startAnimation();
@@ -123,7 +120,6 @@ export class RoomCodeDisplay {
} }
this.#meterFill = 0; this.#meterFill = 0;
this.#meterTarget = 0; this.#meterTarget = 0;
this.#meterPulseFired = false;
const { header, footer, codePart1, codePart2 } = this.#elements ?? {}; const { header, footer, codePart1, codePart2 } = this.#elements ?? {};
if (!header || !footer || !codePart1 || !codePart2) { if (!header || !footer || !codePart1 || !codePart2) {
@@ -378,16 +374,10 @@ export class RoomCodeDisplay {
const header = this.#elements?.header; const header = this.#elements?.header;
if (!header) return; if (!header) return;
if (this.#meterFill >= 1 && !this.#meterPulseFired) { if (this.#meterFill >= 1) {
this.#meterPulseFired = true;
header.classList.add('meter-full-pulse'); header.classList.add('meter-full-pulse');
header.addEventListener('animationend', () => { } else {
header.classList.remove('meter-full-pulse'); header.classList.remove('meter-full-pulse');
}, { once: true });
}
if (this.#meterFill < 1) {
this.#meterPulseFired = false;
} }
} }
} }

View File

@@ -52,7 +52,7 @@
} }
#header.meter-full-pulse { #header.meter-full-pulse {
animation: meter-full-pulse 0.6s ease-out; animation: meter-full-pulse 1.2s ease-in-out infinite;
} }
#footer { #footer {