diff options
| author | Adam Malczewski <[email protected]> | 2026-09-07 17:34:27 +0900 |
|---|---|---|
| committer | Adam Malczewski <[email protected]> | 2026-09-07 17:34:27 +0900 |
| commit | 33d69a11e197d9aced4ce0ecff58898314f26482 (patch) | |
| tree | 70f980dffa18c7796e64a8ebc43672755f4f9ec8 /backend-handoff.md | |
| parent | c43250c16356be523201c2a685d527936aeea0bd (diff) | |
| download | dispatch-web-33d69a11e197d9aced4ce0ecff58898314f26482.tar.gz dispatch-web-33d69a11e197d9aced4ce0ecff58898314f26482.zip | |
fix(workspaces): tile-grid drag bugs — stuck drop, grab-offset follow, empty-cell hover
Three drag-interaction bugs on the Win8 tile home, one shared root cause
(capture loss from DOM reordering) plus two wiring defects:
- DROP NEVER COMMITS (stuck tile): displacePlace returned the displacement
preview SORTED BY STREAM ORDER, so crossing stream positions moved the
dragged tile's DOM node in the keyed {#each} and the browser dropped its
pointer capture — pointerup never landed, phase stayed "dragging", the
follow transform never cleared. displacePlace now preserves the INPUT
render order (coordinates change only); placeAtCell re-sorts to stream
order itself, so the commit's order-renumbering semantics are unchanged.
- FOLLOW TRANSFORM OFFSET: the follow translate was raw pointer displacement,
so a grab away from the tile's top-left made the tile jump (its ORIGIN rode
the pointer). gridPointerDown records the grab offset (pointer minus the
tile's rect) and followStyle cancels the tile's true grid anchor (targetCell
origin), so the GRAB POINT tracks the pointer.
- CAN'T HOVER EMPTY CELLS: pointer handling moved from per-tile elements to
the GRID CONTAINER, which captures the pointer and is never re-parented,
never pointer-events:none, never unmounted — move/up stream to it over
empty cells and off-canvas, and capture can never be lost to a DOM move.
Tests updated: the four order-sensitive displacePlace assertions now expect
input render order (all coordinates unchanged — the plan's stream examples
still hold); HomeTileGrid drag tests still pass via event bubbling.
Verification: svelte-check 0 errors/0 warnings; vitest 1689/1689; biome clean
on touched files; vite build succeeds. Pointer capture is browser-only —
human check at the page: (1) drag a tile across columns, release — it must
drop, not stay stuck; (2) grab a tile by its corner/center — the grabbed
point must stay under the cursor; (3) hover/drag over empty cells past the
last tile — the ghost + drop must keep tracking.
Diffstat (limited to 'backend-handoff.md')
| -rw-r--r-- | backend-handoff.md | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/backend-handoff.md b/backend-handoff.md index f50de69..07240ab 100644 --- a/backend-handoff.md +++ b/backend-handoff.md @@ -268,3 +268,25 @@ changes, NO contract changes — the wire types and every endpoint consumed are it is still the concurrency-priority flag on `Workspace.starred`. - The create flow now calls `ensure(id)` directly (today's navigation-implicit ensure) — same endpoint, no new surface. + +### Follow-up: three drag-interaction bugfixes (2026-09-07, same branch, FE-only) +- **Stuck-tile drop** (`displacePlace` in `logic/tile-layout.ts`): the displacement preview + returned placements SORTED BY STREAM ORDER, so as the dragged tile crossed stream positions the + keyed `{#each}` moved its DOM node and the browser silently dropped its pointer capture — the + subsequent `pointerup` never landed and the follow transform never cleared (phase stuck + `"dragging"`). `displacePlace` now returns the INPUT render order (coordinates change only); + `placeAtCell` re-sorts to stream order itself so the commit's order-renumbering semantics are + unchanged. +- **Follow-transform grab offset** (`ui/HomeTileGrid.svelte`): the drag follow was a raw + pointer-displacement translate, so a grab away from the tile's top-left corner made the tile + jump (its origin rode the pointer instead of the grabbed point). `pointerdown` now records the + grab offset (pointer − tile rect) and the transform cancels the tile's true grid anchor, so the + GRAB POINT tracks the pointer. +- **Empty-cell hover** (`ui/HomeTileGrid.svelte`): pointer handling moved from the per-tile + elements to the GRID CONTAINER, which `setPointerCapture`s the pointer and never gets + re-parented/`pointer-events: none`/unmounted — so move/up stream to it over empty cells and off + the canvas, and capture can never be lost to a DOM move again. +- Verification: `typecheck` 0 errors/0 warnings, vitest 1689/1689 (incl. updated + `tile-layout.test.ts` order assertions — coordinates unchanged), biome clean on touched files, + `build` succeeds. Browser-only (pointer capture) — needs a human at the page to confirm the + three fixes live (see commit message checklist). |
