Two bugs, reproduced in a real browser before fixing.
**The drag died on the first hand-over (touch).** Reordering the list live
meant React moved the pressed wrapper node — losing the pointer capture — and
re-rendered whichever item now occupied a position-dependent slot; the navbar's
raised centre tab is a structurally different <a>, so the very anchor the finger
went down on got unmounted. A browser cancels the touch whose target left the
document, so the drag was cancelled and the order snapped back. Traced with a
MutationObserver alongside the pointer events: reorder → lostpointercapture →
anchor remount → pointercancel.
The DOM order is now frozen for the whole drag and the rearrangement is
expressed purely as transforms, computed from slot geometry measured once at
pickup; only the drop commits a real reorder, after the pointer is gone. The
held item's invisible in-slot copy also keeps rendering with its pre-pickup
props so its node is never replaced. Nothing in the DOM moves, so nothing can
cancel the gesture.
That also removes the FLIP bookkeeping wholesale: with the geometry fixed, no
re-measuring, no settle timers and no animation lock, and a fast drag can no
longer outrun the shuffle. The layout model reflows from each item's own size
and the original gaps, so a list of unequal items (an expanded shortcut card
among collapsed ones) lands correctly.
**Hold-to-pick-up never fired with a mouse.** Any travel over 10px during the
1.4s cancelled the hold — but a hand resting on a mouse drifts well past that,
so on desktop the pickup essentially never happened. Travel now only cancels
for touch and pen, where it means "I'm scrolling"; a mouse can't scroll with the
button held. The pickup uses the pointer's current position rather than where it
went down, so the item doesn't jump out from under a drifted cursor.
Also: the slot hand-over threshold sits just short of the midpoint, so aiming at
the middle of the item you want reliably takes that slot instead of being a coin
flip that left the item one short.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>