From 6ceca4fbae11a8c253cf1680809d2a16f16d378e Mon Sep 17 00:00:00 2001 From: Graham Barber Date: Thu, 14 May 2026 19:03:18 -0700 Subject: [PATCH] fix(wc): IntersectionObserver doesn't navigate during role swap The IO that drives audience-mode scroll navigation kept firing during the layout transition into presenter mode: as slides shifted between slot states the IO saw them passing through the host's viewport and sent navigate.scroll for each one, marching currentIndex through every slide before settling on whichever fired last. Gate fireUpdates on role==='audience'. The IO only makes sense for scroll-driven navigation in the audience layout; presenter navigation goes through keyboard/buttons via explicit navigate.next/previous. Co-Authored-By: Claude Opus 4.7 --- packages/wc/components/presentation/wc.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/wc/components/presentation/wc.ts b/packages/wc/components/presentation/wc.ts index f3e6047..604f931 100644 --- a/packages/wc/components/presentation/wc.ts +++ b/packages/wc/components/presentation/wc.ts @@ -385,6 +385,12 @@ export class PresentationWC extends LitElement { } fireUpdates(entries: IntersectionObserverEntry[]) { + // IO drives audience-mode scroll navigation. In presenter mode the + // host stops scrolling and slides redistribute into named slots; the + // resulting flurry of intersection changes would otherwise feed + // bogus `navigate.scroll` events into xstate and march currentIndex + // through every slide before settling at the last one to fire. + if (this.role !== "audience") return; for (const entry of entries) { if (entry.isIntersecting) { this.presentation.send({ -- 2.51.2