PagePane: drops in a row edge zone silently no-op (gap slots collapse before the drop-time recompute) #127
Labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Cloonar/deckle#127
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Pre-existing bug — surfaced by the real-browser smoke test during #124 / PR #126, and reproduced bit-for-bit on a
mainbuild, so it does not originate from that refactor. Filed separately here because PR #126's body claimed it had been filed and it had not; the finding would otherwise be lost in a merged PR description.Symptom
In PagePane, a drag that is released while the pointer sits in a row's before/after edge zone can silently do nothing — no move, no error, no indicator left behind. The element simply stays put.
Dropping on the gap slots — the primary affordance, the explicit insertion points between rows — lands correctly. Only the row-edge zones are affected, which makes this easy to miss: the feature appears to work until a user aims at a row edge instead of a gap.
Mechanism (as diagnosed during the smoke test)
getBoundingClientRect()on the row, reading the post-shift rect while using the drop event's originalclientY.ok, so the move is skipped.The drop-time recompute is deliberate and correct in intent — the pointer genuinely may cross a zone boundary since the last
dragoverpainted the indicator. The bug is that it recomputes against geometry that the clear step has already invalidated.Where to look
web/src/components/PagePane.tsx—rowDrop, which callsrowZoneAt(e, item)inside thereorder.dropaction, i.e. after the primitive has cleared all drag state.web/src/dragReorder.ts—drop()clears state and then runs the action. This ordering is intentional (actions receive the drag value as an argument precisely so they never re-read a cleared signal), so a fix likely belongs on the PagePane side rather than in the primitive.Likely fix directions, for whoever triages: capture the row rect (or the resolved zone) before clearing, and hand it to the action — or defer the visual collapse until after the verdict resolves. Both need weighing against the reason the recompute exists.
Why jsdom cannot catch this
The failure is entirely geometric: it depends on real layout, real
getBoundingClientRect()values, and a real reflow when the gap slots un-render. jsdom renders every rect zero-height, so the shift is zero and the recompute always agrees with the original zone. Any regression test for this needs the repo's playwright-core + nix Chromium recipe againstharness serve.Scope note
TreePane also does a drop-time zone recompute, but its rows do not collapse on clear, so it is not obviously affected. Worth confirming during triage rather than assuming.
Related: #124 (the primitive extraction), PR #126 (where this was found).