30% offEnding soon
FSD-010Frontend system design Premium

Design a Drag-and-Drop Framework

Design an accessible drag-and-drop framework with input parity, hit testing, auto-scroll, optimistic moves, rollback, and undo.

Intermediate 50 min read

Build drag and drop as an input-independent move engine. Sensors translate pointer, touch, pen, keyboard, and menu actions into one session model. A geometry layer finds valid destinations, the preview shows intent without mutating data, and a transaction layer commits at most one stable move operation with rollback and undo.

A draggable card is easy to demo and surprisingly hard to trust. The trouble starts when a finger scrolls instead of dragging, two drop zones overlap, a list moves under auto-scroll, a keyboard user needs the same outcome, or the server rejects an optimistic reorder. A reusable framework has to make those cases ordinary.

Start with a move intent, not DOM movement

The framework should describe what the user means before it changes application data. A move intent contains a stable source ID, a destination container, an anchor or insertion position, and an operation such as move, copy, or link. Pointer coordinates are evidence used to derive that intent. They are not the persisted result.

Keep four concerns separate:

  • sensors turn input events into activation, movement, release, and cancellation;
  • geometry and policy choose a compatible destination;
  • presentation draws the preview, placeholder, indicators, and announcements;
  • the host application validates and persists a move intent.

This separation lets a keyboard command, a touch drag, and a visible "Move to" menu produce the same transaction. It also keeps visual experiments out of ordering logic.

The public interview prompt

Design a reusable drag-and-drop framework for a large web product. Explain:

  • pointer, touch, pen, keyboard, and non-dragging pointer alternatives;
  • activation constraints, pointer capture, cancellation, and native browser behavior;
  • draggable and drop-target registration, nested targets, portals, and virtualization;
  • geometry measurement, hit testing, insertion edges, axis locking, and auto-scroll;
  • previews, placeholders, focus, screen-reader announcements, and reduced motion;
  • move, copy, and link intents across lists and constrained item types;
  • optimistic updates, idempotent persistence, conflicts, rollback, and undo;
  • performance budgets, cleanup, observability, testing, and staged adoption.

Assume a workspace may register 2,000 mounted candidates across nested scroll containers. A typical interaction moves one item within or between ordered lists. Collaborative updates can change neighboring items while a drag is active. These are design assumptions, not measured product facts. Operating-system file transfer, freehand drawing, and cross-origin dragging are outside version one.

What the premium solution covers

The complete solution defines sensor and adapter contracts, an explicit session state machine, geometry snapshots, deterministic nested hit testing, edge-based insertion, auto-scroll ownership, accessible alternatives, announcements, preview rendering, virtualized targets, a stable move-operation API, optimistic reconciliation, rollback, undo, security boundaries, metrics, tests, and an interview scoring rubric.

Original media follows a pointer session from press through commit, maps one coordinate into nested semantic targets, compares equivalent input paths, and traces an optimistic operation through acknowledgement or correction. Two deterministic labs expose target selection and transaction reconciliation without relying on browser drag events or a backend.

Premium solution

Continue with the complete system design

Unlock the architecture, state machine, API contracts, original diagrams, positioning model, accessibility decisions, performance budgets, testing plan, rollout strategy, scoring rubric, and interview walkthrough.

  • Detailed, beginner-friendly explanation
  • Production failure modes and trade-offs
  • Mobile-friendly architecture diagrams
  • Senior and staff-level interview signals
Unlock Premium

Frequently asked questions

Should an in-page drag-and-drop framework use the native HTML Drag and Drop API?
Use native drag and drop when the browser must exchange files, links, or serialized data with the operating system or another document. A product-owned in-page move often needs Pointer Events for touch behavior, frame-level geometry, custom previews, and precise auto-scroll. Keep both behind adapters rather than forcing one sensor onto every use case.
How do you make drag and drop keyboard accessible?
Provide explicit move controls or a keyboard move mode that creates the same move intent as pointer dragging. Announce pickup, valid destinations, movement, cancellation, and completion. Keyboard support is necessary, but WCAG also requires a non-dragging single-pointer alternative when dragging is not essential.
How should drop targets be chosen when they overlap?
Filter incompatible and disabled targets first. Then rank candidates with a deterministic policy such as deepest owned target, target priority, pointer containment, and distance to an insertion edge. The engine should return a semantic destination, not mutate the DOM during hit testing.
How does auto-scroll work without making dragging unstable?
Choose one scroll owner per axis, derive velocity from pointer distance inside an edge zone, cap acceleration, and update scroll in requestAnimationFrame. Re-measure affected geometry after scrolling and run hit testing again from the latest pointer sample.
What should happen if the server rejects an optimistic move?
Persist a stable move operation with source, destination, anchor IDs, base revision, and operation ID. On rejection, reconcile against the latest snapshot. Roll back by stable identity, not old array indexes, and announce the outcome. Offer undo as a new inverse operation after a successful commit.
Should the dragged DOM element follow the pointer?
Usually render a separate lightweight preview in a fixed overlay and leave a placeholder at the source. This avoids moving the semantic element out of its list, reduces layout churn, and lets the original item keep a predictable focus and ownership relationship.