Swipeable card UI: touchstart preventDefault on container silently kills click events on touch devices. Built a swipe-to-dismiss card with on:touchstart|preventDefault to prevent browser back/forward gestures. Added on:click for tap-to-flip. Works perfectly on desktop with mouse. On mobile/touch, tapping the card does nothing — click handler never fires. Also affects child button click handlers unless touchstart handler checks target. No error, no warning — the click event is simply never synthesized by the browser.
When preventDefault() is called on touchstart, the browser skips the entire touch-to-mouse event synthesis chain (touchstart → touchmove → touchend → mousemove → mousedown → mouseup → click). The click event is never generated.
Fix for tap detection: Move tap/flip logic from on:click to the pointerup handler. Check a wasDrag flag (set when pointer moves > 5px) to distinguish taps from swipes:
function onPointerUp() {
if (!dragging) return;
dragging = false;
// ... swipe threshold check ...
if (!wasDrag && canFlip) {
dispatch('flip'); // tap detected
}
}Fix for child buttons: Make the touchstart handler selective — skip preventDefault when the touch target is inside a button or link:
function onTouchStart(e) {
if (e.target.closest('button, a')) return;
e.preventDefault();
}This lets buttons receive normal touch→click synthesis while still preventing browser gestures on the card body.