fix(client): make colonist roster card clicks 100% reliable (fixes #16) #17

Merged
agent-gemini merged 1 commit from gemini/16-colonist-click-reliability into main 2026-10-18 10:04:38 +02:00
Collaborator

Fixes #16

Root Cause

  1. renderColonistRoster() was executing bar.innerHTML = '' and regenerating all DOM elements (.colonist-pill) on every tick/delta (10 Hz).
  2. When a player clicked on a colonist card:
    • mousedown hit element A.
    • A tick delta arrived within milliseconds, replacing element A with new element B.
    • mouseup hit element B.
    • The browser suppressed the click event because the start and end target nodes were different instances.
  3. This dropped mouse clicks frequently, forcing the user to click multiple times until a click happened to fall entirely within an inter-delta frame.

Solution

  1. Reused DOM Elements by ID: renderColonistRoster() now updates existing DOM nodes in-place without clearing bar.innerHTML. Elements are only created once per pawn and pruned when removed.
  2. Event Delegation: Added a stable delegated click listener on the static parent #colonist-roster-bar using .closest('.colonist-pill') and data-pawn-id.
  3. CSS UX: Added user-select: none; on .colonist-pill to prevent accidental text highlight during quick consecutive clicks.
Fixes #16 ### Root Cause 1. `renderColonistRoster()` was executing `bar.innerHTML = ''` and regenerating all DOM elements (`.colonist-pill`) on every tick/delta (10 Hz). 2. When a player clicked on a colonist card: - `mousedown` hit element $A$. - A tick delta arrived within milliseconds, replacing element $A$ with new element $B$. - `mouseup` hit element $B$. - The browser suppressed the `click` event because the start and end target nodes were different instances. 3. This dropped mouse clicks frequently, forcing the user to click multiple times until a click happened to fall entirely within an inter-delta frame. ### Solution 1. **Reused DOM Elements by ID**: `renderColonistRoster()` now updates existing DOM nodes in-place without clearing `bar.innerHTML`. Elements are only created once per pawn and pruned when removed. 2. **Event Delegation**: Added a stable delegated click listener on the static parent `#colonist-roster-bar` using `.closest('.colonist-pill')` and `data-pawn-id`. 3. **CSS UX**: Added `user-select: none;` on `.colonist-pill` to prevent accidental text highlight during quick consecutive clicks.
Sign in to join this conversation.
No description provided.