C1.08.5Drag cancellation and return to origindesign

Drag and drop can be cancelled and returned to origin

Aliases: cancel drag · drag cancel · return to origin

What it is

Drag and drop should support cancellation and return to origin: when people discover mid-transport that the object or destination is wrong, they can back out without leaving any trace on existing state, and the object springs back to its start position. Cancellation differs from an error surfaced after an invalid drop — an error means the commit already happened and now needs undoing; cancellation means the commit never happened at all, so nothing should need undoing.

Why it happens

Leaving no trace requires that pickup never touch the underlying data, only a temporary visual binding: the object's display layer follows the pointer while its real position in the list, file system, or document stays untouched until the drop commits. Under that design, cancelling just destroys the temporary binding — no rollback logic needed. The fragile alternative, sometimes chosen for snappier cross-list visual feedback, optimistically removes the object from its source list at pickup time. Then cancellation becomes "undo a deletion that already happened," and if the source list changed during the drag — background sync, a collaborator's concurrent edit — a naive undo can no longer restore the exact original position, forcing bespoke state-recovery code that is itself a new source of bugs.

Triggers for cancellation are not interchangeable: pressing Escape on desktop is an explicit cancel command; dragging the object back near its origin and releasing relies on hit-testing treating "return to source" as a special valid target; releasing in a dedicated safe-cancel zone (some systems treat dropping outside the window bounds this way) is a third option; touch has no Escape key, so it depends entirely on the latter two.

Where it stops holding

Cancellation can only unwind what has not yet committed — it cannot conceal side effects already triggered mid-drag. Cross-application drags sometimes pre-start a file copy, upload, or autosave once the pointer hovers over a target long enough, precisely so the drop itself feels instantaneous; cancelling at that point must state plainly whether the pre-started action can actually be aborted, not pretend nothing happened. Web apps built on the native HTML5 Drag and Drop API are a separate boundary case: the browser owns the drag session's start and end, application code receives a limited event set, and whether Escape triggers cancellation — and whether the browser then fires a consistent set of cleanup events — depends on the specific browser implementation and cannot be assumed uniform.

Applying it

  • Keep pickup a purely visual binding; leave real data untouched until drop. This implementation choice is what makes cancellation cheap and reliable in the first place.
  • Give mouse, touch, keyboard, and assistive input their own reachable cancel triggers — touch needs at least "drag back to origin" and "release in a safe zone."
  • Design a separate cancel-or-abort affordance for drags that already produced real side effects (upload, cross-app copy, autosave); do not reuse ordinary drag feedback for them.
  • How to check: trigger cancellation at three points — right after pickup, mid-transport, and near an invalid target — and diff the data snapshot before and after each cancel; also verify selection state and keyboard focus are restored, not just the object's position.

Related

  • Same group: C1.08.1 Drag and drop has three phases: pickup, transport, and drop · C1.08.2 Drag-start thresholds prevent a click from becoming a drag · C1.08.3 Valid drop targets must be explicit during drag · C1.08.4 Auto-scroll when dragging to an edge · C1.08.6 Drag and drop needs a non-drag equivalent
  • Nearby: I1 State, time, and response · C1.07 Single and double click
  • Search terms: drag cancellation · return to origin · reversible interaction

Cards in the same group

Quick Actions

Share

Share this page

ios_share

https://hci.top/en/handbook/C1.08.5