From 48b23a8132537209c338aa04311f8057b1f5f5b5 Mon Sep 17 00:00:00 2001 From: Adam Malczewski Date: Mon, 7 Sep 2026 18:00:04 +0900 Subject: fix(workspaces): mobile (tall) grid can't scroll — root height collapse + touch capture MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two blockers for scrolling the tall grid on a phone: 1. HomeTileGrid's root was `flex-1` inside a BLOCK parent (the workspace region), so flex-1 did nothing and the root sized to its content; the scroller's `h-full` collapsed to auto and overflow-y-auto never engaged — extra tiles were clipped by the shell's `overflow-hidden` with no way to scroll. The root is now `h-full`, so the scroller gets a definite height and tall mode scrolls (wide mode was unaffected: horizontal overflow scrolls regardless of container height). 2. `setPointerCapture` was called for TOUCH pointers at pointerdown, which can suppress native panning in WebKit. Touch now skips explicit capture: the browser's implicit capture already retargets the press, and after the long-press lift the moved events bubble up to the grid container where the handlers live — scroll gestures keep working and touch drags are intact. Verification: svelte-check 0 errors/0 warnings; vitest 1694/1694; build ok. Needs a human on a real phone: swipe the tall grid when tiles overflow — it must scroll; long-press-and-drag a tile must still reorder. --- src/features/workspaces/ui/HomeTileGrid.svelte | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/features/workspaces/ui/HomeTileGrid.svelte b/src/features/workspaces/ui/HomeTileGrid.svelte index d259aea..489c783 100644 --- a/src/features/workspaces/ui/HomeTileGrid.svelte +++ b/src/features/workspaces/ui/HomeTileGrid.svelte @@ -160,7 +160,12 @@ if (!tileEl || insideInteractive(e.target)) return; const id = tileEl.getAttribute("data-tile-id"); if (id === null) return; - gridEl?.setPointerCapture?.(e.pointerId); + // Capture mouse/pen so fast drags keep streaming to this container. TOUCH + // is purposely NOT captured here: an early touch capture can suppress + // native scrolling (WebKit), and touch already gets the browser's implicit + // capture — after the long-press lift the moved events bubble up to this + // container anyway. + if (e.pointerType !== "touch") gridEl?.setPointerCapture?.(e.pointerId); // Where within the tile the pointer grabbed — the follow transform keeps // THIS point under the pointer (not the tile's top-left origin). const rect = tileEl.getBoundingClientRect(); @@ -453,7 +458,7 @@ -
+