Skip to main content
Version: next

Gestures Overview

React UI Animate has two layers for handling pointer/touch/wheel input:

  • Gesture + useGesture: the low-level primitive. Gesture.Pan(), .Move(), .Wheel(), .Scroll(), .Swipe(), .Hover(), .Pinch(), and .Rotate() are chainable builders that describe a gesture; useGesture attaches the built descriptor to a ref, an array of refs, or window. Every gesture type is registered against the same shared per-element tracker, so multiple useGesture calls on one node compose instead of fighting each other.
  • useDrag: a high-level convenience hook built on top of Gesture.Pan(). It returns ready-to-use x/y AnimateValues with momentum, bounds, and rubber-banding built in, so you don't have to wire withDecay/withSpring yourself for the common drag-a-thing case.

Reach for useDrag first for draggable elements. Reach for Gesture + useGesture for anything else: scroll tracking, wheel/zoom controls, swipe detection, hover/cursor effects, or pinch-to-zoom and rotate.

tip

Start with useDrag for the common case. Drop down to useGesture when you need a gesture type that isn't drag.

Available gesture types

BuilderFiresUse it for
Gesture.Pan()onStart / onChange / onEnd / onFinalizeCustom drag logic (useDrag covers most of this already)
Gesture.Move()onStart / onChange / onEndCursor-follow effects, hover-position tracking
Gesture.Wheel()onStart / onChange / onEndTrackpad/wheel-driven zoom or custom scroll
Gesture.Scroll()onStart / onChange / onEndScroll-linked animation, parallax, progress bars
Gesture.Swipe()onSwipe (once, on release)Flick-to-dismiss, carousels, swipe navigation
Gesture.Hover()onStart / onChange / onEndHover-in/out state
Gesture.Pinch()onStart / onChange / onEnd / onFinalizeTwo-finger zoom
Gesture.Rotate()onStart / onChange / onEnd / onFinalizeTwo-finger rotation

See useGesture for the full API and one example per builder, and useDrag for the drag convenience hook.

Common pattern: drag with a spring back

import { useRef } from 'react';
import { useDrag, animate } from 'react-ui-animate';

function DraggableCard() {
const ref = useRef(null);
const { x, y } = useDrag(ref);

return (
<animate.div
ref={ref}
style={{ translateX: x, translateY: y, cursor: 'grab' }}
>
Drag me
</animate.div>
);
}

useDrag springs back to bounds automatically when bounds is set, and flings with momentum on release by default. See useDrag for every option.

Best practices

Do

  • Animate translateX/translateY (GPU-accelerated transforms), not left/top.
  • Let useDrag's momentum/elastic/bounds options do the physics work instead of hand-rolling withDecay for simple drag cases.
  • Pass a stable ref. Gesture registration happens once on mount and stays live for config/handler changes, but the element itself isn't expected to swap out from under it.

Don't

  • Don't skip a fallback/keyboard interaction for anything gesture-driven. Gestures should enhance an already-usable UI, not be the only way to trigger an action.
  • Don't set overly small minDistance/threshold values. A little slop avoids gestures firing on what was meant to be a click/tap.