From 397855c9aba6f4de2f7a4d0d5d70b4379fdb3139 Mon Sep 17 00:00:00 2001 From: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta Date: Sun, 2 Aug 2026 20:05:40 -0400 Subject: [PATCH] fix(desktop): scope wheel exemption to active terminal Co-authored-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta Signed-off-by: npub1mprnacetjua2xx3p5eddmhxyk6wv929ymm5py8kd2xfxurxahspqqlgyta --- .../hooks/useWebviewScrollBoundaryLock.ts | 2 +- desktop/tests/e2e/overscroll-boundary.spec.ts | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/desktop/src/shared/hooks/useWebviewScrollBoundaryLock.ts b/desktop/src/shared/hooks/useWebviewScrollBoundaryLock.ts index 88717b9ea..50d132ec0 100644 --- a/desktop/src/shared/hooks/useWebviewScrollBoundaryLock.ts +++ b/desktop/src/shared/hooks/useWebviewScrollBoundaryLock.ts @@ -2,7 +2,7 @@ import * as React from "react"; const BOUNDARY_EPSILON_PX = 1; const CONVERSATION_SCROLL_SELECTOR = "[data-buzz-conversation-scroll]"; -const TERMINAL_SUBSTRATE_SELECTOR = "[data-terminal-owner]"; +const TERMINAL_SUBSTRATE_SELECTOR = '[data-terminal-owner="terminal"]'; const SCROLLABLE_OVERFLOW_VALUES = new Set(["auto", "scroll", "overlay"]); function isHTMLElement(value: EventTarget | null): value is HTMLElement { diff --git a/desktop/tests/e2e/overscroll-boundary.spec.ts b/desktop/tests/e2e/overscroll-boundary.spec.ts index 64a931e60..e7e561c12 100644 --- a/desktop/tests/e2e/overscroll-boundary.spec.ts +++ b/desktop/tests/e2e/overscroll-boundary.spec.ts @@ -70,7 +70,7 @@ test("locks viewport rubber-band outside conversation scrollers", async ({ // gesture alone so the substrate's own handler can receive it. await page.evaluate(() => { const terminal = document.createElement("section"); - terminal.dataset.terminalOwner = "buzz"; + terminal.dataset.terminalOwner = "terminal"; terminal.dataset.testid = "terminal-wheel-target"; document.body.append(terminal); }); @@ -112,18 +112,43 @@ test("locks horizontal viewport pan everywhere", async ({ page }) => { await page.evaluate(() => { const terminal = document.createElement("section"); - terminal.dataset.terminalOwner = "buzz"; + terminal.dataset.terminalOwner = "terminal"; terminal.dataset.testid = "terminal-wheel-target"; document.body.append(terminal); }); - for (const deltaX of [-120, 120]) { + for (const [deltaX, deltaY, prevented] of [ + [120, 0, true], + [0, 120, false], + [120, 120, false], + [120, 20, true], + ] as const) { await expect( dispatchWheelPrevented(page, '[data-testid="terminal-wheel-target"]', { deltaX, + deltaY, }), - ).resolves.toBe(true); + ).resolves.toBe(prevented); } + // A concealed substrate is not an active custom wheel consumer. Keep dead + // space locked even if a future layout places Buzz content inside it. + await page.evaluate(() => { + const terminal = document.querySelector( + '[data-testid="terminal-wheel-target"]', + ); + const buzzContent = document.createElement("div"); + buzzContent.dataset.testid = "concealed-terminal-dead-space"; + terminal?.append(buzzContent); + if (terminal) terminal.dataset.terminalOwner = "buzz"; + }); + await expect( + dispatchWheelPrevented( + page, + '[data-testid="concealed-terminal-dead-space"]', + { deltaY: 120 }, + ), + ).resolves.toBe(true); + // A predominantly vertical gesture with slight horizontal drift still // reaches the conversation scroller. await expect(