From 79567264e0f454d1b1531dc7301b8f364fa7522b Mon Sep 17 00:00:00 2001 From: Test Date: Sat, 25 Apr 2026 23:31:12 -0700 Subject: [PATCH] fix(guidance): Stop button taps drop because render() destroys button mid-tap MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updateGuidance() is called on every GPS fix (~1 Hz on a moving phone) and ends with render(), which does panelEl.innerHTML = '' and recreates the Stop button. iOS Safari tracks the specific DOM element that received touchstart — if it's removed before touchend, no click is synthesized and the tap is silently dropped. With GPS fixes coming faster than typical tap timing, almost every tap lands in the rebuild window. Switch to event delegation: a single persistent click listener on panelEl that checks .closest('.guidance-btn') and calls onStop. The listener survives every render; buttons can come and go without breaking the touch path. Also adds type="button" to the buttons defensively. Closes #179 Co-Authored-By: Claude Opus 4.7 (1M context) --- src/guidance.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/guidance.ts b/src/guidance.ts index bee159d..84f5561 100644 --- a/src/guidance.ts +++ b/src/guidance.ts @@ -76,6 +76,11 @@ export function addGuidanceControl( panelEl = c; L.DomEvent.disableClickPropagation(c); L.DomEvent.disableScrollPropagation(c); + // Delegate clicks on .guidance-btn to a single persistent listener so + // every-GPS-fix re-renders don't destroy the button mid-tap. + L.DomEvent.on(c, 'click', (e: Event) => { + if ((e.target as HTMLElement).closest('.guidance-btn')) onStop(); + }); render(); return c; }, @@ -386,10 +391,11 @@ function render(): void { function appendButton(label: string, modifier: string, ariaLabel: string): void { if (!panelEl) return; const btn = document.createElement('button'); + btn.type = 'button'; btn.className = `guidance-btn ${modifier}`; btn.textContent = label; btn.setAttribute('aria-label', ariaLabel); - btn.addEventListener('click', onStop); + // Click handling lives on panelEl via delegation — see addGuidanceControl. panelEl.appendChild(btn); }