Gesture & drag

Teaching your UI to understand flicks, swipes, and drags

Drag requires frame-by-frame response: zero perceptible lag, resistance at boundaries, natural settle on release.

Pointer capture

Without setPointerCapture, the element loses track of the cursor the moment it escapes bounds.

Always use pointer events, not mouse events. Pointer events unify mouse, touch, and stylus.

Momentum

Track the last 2-3 pointer positions with timestamps. Compute velocity as deltaPosition / deltaTime. Pass that velocity to a spring.

Motion's drag prop handles this automatically.

Boundary damping

Apply logarithmic damping past the boundary:

0.55 is iOS's value. 0.3 feels stiffer. 0.8 feels loose.

Swipe-to-dismiss

Use both distance and velocity, never just one.

If neither is met, spring back. On dismiss, animate off-screen with current velocity.

Touch-action and scroll conflict

Axis locking

On the first pointermove, lock to whichever axis has the larger delta.

Apply a 5-8px dead zone before checking.

The 60fps requirement