Fix: Klick auf Bildwechsel-Pfeil der Produktkarte öffnete ungewollt die Produktseite

Bug: bei Produkten mit mehreren Fotos (z.B. Armbändern) sprang ein Klick auf den ‹/›-Pfeil
zum Bildwechsel kurz zum nächsten Foto und öffnete dann trotzdem sofort die volle
Produktseite. Ursache: Astros <ClientRouter /> (View-Transitions, siehe Layout.astro) fängt
Klicks auf <a>-Links über einen eigenen, früher registrierten document-Klick-Listener in der
Bubble-Phase ab und startet die Navigation, BEVOR der Karussell-Klick-Handler von ProductCard
(der ebenfalls in der Bubble-Phase lief) preventDefault()/stopPropagation() aufrufen konnte.

Fix: Karussell-Klick-Handler läuft jetzt in der Capture-Phase (wie schon beim benachbarten
Wisch-Sperr-Handler etwas weiter unten in derselben Datei) — läuft dadurch garantiert vor
ClientRouters eigenem Listener und verhindert die Navigation zuverlässig, bevor sie startet.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
qcigano
2026-08-04 13:55:10 +02:00
co-authored by Claude Sonnet 5
parent d9e59ab585
commit aeb76a277d
+9 -1
View File
@@ -101,6 +101,14 @@ const desc = product.beschreibung[lang];
dots.forEach((dot, i) => dot.classList.toggle("is-active", i === clamped));
}
// WICHTIG: Capture-Phase (letztes Argument "true"), NICHT die normale Bubble-Phase — sonst
// gewinnt Astros <ClientRouter /> (siehe Layout.astro) das Wettrennen: der ist schon im <head>
// registriert und fängt Klicks auf den umschließenden <a class="product-card">-Link BEVOR
// dieser Handler hier (Bubble-Phase würde erst NACH ClientRouter laufen) überhaupt
// preventDefault() aufrufen kann — genau das führte zu dem Bug, dass ein Klick auf den
// Bildwechsel-Pfeil kurz das zweite Foto zeigte und dann trotzdem sofort zur Produktseite
// weiterspringt. Capture-Phase auf document läuft IMMER vor jeder Bubble-Phase-Verarbeitung
// (auch vor ClientRouters eigenem Listener), genau wie beim Wisch-Sperr-Handler weiter unten.
document.addEventListener("click", (e) => {
const target = e.target as HTMLElement;
const control = target.closest<HTMLElement>(".carousel-btn, .carousel-dot");
@@ -116,7 +124,7 @@ const desc = product.beschreibung[lang];
} else {
karussellWechseln(media, current + Number(control.dataset.dir));
}
});
}, true);
// Wischen/Swipen (Finger auf dem Handy, Maus ziehen am PC) — überall auf der Seite, wo eine
// Produktkarte mit mehreren Fotos vorkommt. Pointer Events statt separater Touch-/Maus-Logik,