fix(outline): PROG-119 land drag-drops in the same frame as the drop#95
Merged
Conversation
Dropping a dragged outline row flashed: the row snapped back to its old slot for a frame or two, then jumped to the drop position. dnd-kit clears its drag transforms synchronously in the drop event, but React Query v5 defers cache-subscriber notification through setTimeout(0), so the optimistic rank write painted one-two frames late. The board dodged this with a local columns mirror (PROG-59); the Outline renders straight from the snapshot cache, so all three of its drag surfaces (rows, arc sections, focus sections) showed the flash. Set a pass-through notifyManager scheduler so cache writes notify synchronously (React Query v4 behavior). React 18 auto-batching keeps a multi-write drop as one commit, and no code path writes the cache during render. Verified with a headless rAF-sampling driver: new order visible at frame 0 after mouseup (was frame 2), no old-order reappearance, no positional jump, order persists across reload. Decision record in docs/decisions/PROG-119.md.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes the PROG-119 reorder flash: after dropping a dragged outline row, it briefly snapped back to its original slot before jumping to the drop position.
Root cause. dnd-kit clears its drag transforms synchronously inside the drop event, but React Query v5's
notifyManagerdefers all cache-subscriber notification throughsetTimeout(0)— so the browser painted a frame (sometimes two) with the old order and the transforms already gone before the optimistic rank write reached the components. The board never showed this because PROG-59 keeps a localcolumnsmirror updated synchronously inonDragEnd; the Outline renders straight from the snapshot cache, so all three of its drag surfaces (action rows, arc sections, focus sections) flashed.Fix. One line in
store.ts:notifyManager.setScheduler((cb) => cb())— synchronous notification, React Query v4's behavior. React 18 auto-batching still coalesces a multi-write drop (tied-group container renumber) into one commit, and every cache write lives in store.ts's event/async mutation helpers, so nothing writes during render. Every optimistic mutation now paints in the same frame as its event, which is what the instant-UI requirement (SPEC §2.1) wants globally. Alternative (board-style local mirrors × 3 surfaces) rejected indocs/decisions/PROG-119.md.Verification
Headless Playwright driver that drags a top-level outline row and samples the DOM every rAF frame after mouseup:
bun run check,bun test src(170 pass), andbun run format:checkall green.