with-drag-drop
Drag and Drop — Implementation Guidance
Custom pointer-driven dragging, built directly (not native HTML5 draggable/dataTransfer — that's a separate, OS-integrated mechanism this skill does not cover, and no third-party dependency is required for anything below). One core engine, extended per scenario — not several competing approaches to pick between. Apply Core Rules to everything you build; The Core Engine describes the shared shape; Extending the Engine covers each scenario.
The Core Engine
Every scenario below is the same three-part shape, just configured differently:
- Activators — whatever starts/moves/ends the gesture. A pointer activator (pointerdown/move/up, gated by a distance or delay threshold) is the default; a keyboard activator (Space/Enter to pick up, arrow keys to move, Escape to cancel) drives the same start/move/end lifecycle so keyboard operability is architected in, not bolted on afterward.
- Modifiers — an ordered pipeline of pure functions the raw delta passes through before it's applied: restrict-to-bounds, snap-to-grid, aspect-ratio lock, min/max size. Order matters — each modifier sees the previous modifier's already-adjusted values, not the raw pointer position.
- Position model — a
base(the resting value, changed only at gesture start/end) and anoffset(the live delta, changed continuously during the gesture, folded back to zero the instant it ends). See Core Rules for why these stay separate.
A free-drag element is this engine with no modifiers. A resize handle is this engine tracking width/height instead of x/y. A sortable list is this engine plus a swap/shift strategy function. A drop zone is this engine plus a collision-detection function against registered targets. Build the engine once; each scenario in Extending the Engine is a small addition to it, not a separate system.
Core Rules
These apply everywhere in the engine — a naive implementation of any one of these has broken working code in production, including this exact project's own feedback-widget FAB earlier the same day.