Edit Page

#Gestures

A powerful gesture recognition system for the browser.

Motion extends the basic set of event listeners provided by React with a simple yet powerful set of UI gesture recognisers.

It currently has support for hover, tap, pan and drag gesture detection. Each gesture has a series of event listeners that you can attach to your motion component.

#Animation helpers

motion components provide two helper props: whileHover and whileTap. These can define animation targets to temporarily animate to while a gesture is active.

<motion.button
  whileHover={{
    scale: 1.2,
    transition: { duration: 1 },
  }}
  whileTap={{ scale: 0.9 }}
/>

Both props can be set either as a target of values to animate to, or the name of any variants defined via the variants prop. Variants will flow down through children as normal.

<motion.button
  whileTap="tap"
  whileHover="hover"
  variants={buttonVariants}
>
  <svg>
    <motion.path variants={iconVariants} />
  </svg>
</motion.button>

motion components automatically manage the interplay between these while props. So for instance, if hovering starts and stops while the tap gesture is active, the tap gesture receives priority and any properties defined on both will remain in their tapped state.

Likewise, if both gestures are defined and tapping ends, the component will know to animate either to the state defined in whileHover, or the component's original state, depending on whether tapping ends inside or outside of the component.

#A note on SVG filters

The while helper properties won't work on SVG filter components, as these elements don't have a physical presence and therefore don't receive events. To respond to gestures, you need to introduce React state to the component and attach listeners to the physical element.

const MyComponent = () => {
  const [isHovered, setHovered] = useState(false)

  // Simplified example
  return (
    <svg>
      <image
        filter="url(#blur)"
        onMouseEnter={() => setHovered(true)}
        onMouseLeave={() => setHovered(false)}
      />
      <filter id="blur">
        <motion.feGaussianBlur
          initial={false}
          animate={{ stdDeviation: isHovered ? 0 : 2 }}
        />
      </filter>
    </svg>
  )
}

#Hover

The hover gesture detects when a pointer hovers over or leaves a component.

It differs from onMouseEnter and onMouseLeave in that hover is guaranteed to only fire as a result of actual mouse events (as opposed to browser-generated mice events emulated from touch input).

<motion.a
  whileHover={{ scale: 1.2 }}
  onHoverStart={e => {}}
  onHoverEnd={e => {}}
/>

#whileHover: string | TargetAndTransition

Properties or variant label to animate to while the hover gesture is recognised.

<motion.div whileHover={{ scale: 1.2 }} />

#onHoverStart(event, info): void

Callback function that fires when pointer starts hovering over the component.

<motion.div onHoverStart={() => console.log('Hover starts')} />
event: MouseEvent
info: EventInfo

#onHoverEnd(event, info): void

Callback function that fires when pointer stops hovering over the component.

<motion.div onHoverEnd={() => console.log("Hover ends")} />
event: MouseEvent
info: EventInfo

#Tap

The tap gesture detects when a pointer presses down and releases on the same component.

It fires a tap event when tapping successfully completes on an component, and a tapCancel event when tapping ends outside the component.

If the tappable component is a child of a draggable component, it'll automatically cancel the tap gesture if the pointer moves further than 3 pixels during the gesture.

#whileTap: string | TargetAndTransition

Properties or variant label to animate to while the component is pressed.

<motion.div whileTap={{ scale: 0.8 }} />

#onTap(event, info): void

Callback when the tap gesture successfully ends on this element.

function onTap(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTap={onTap} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: TapInfo

An TapInfo object containing x and y values for the point relative to the device or page.

#onTapStart(event, info): void

Callback when the tap gesture starts on this element.

function onTapStart(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTapStart={onTapStart} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: TapInfo

An TapInfo object containing x and y values for the point relative to the device or page.

#onTapCancel(event, info): void

Callback when the tap gesture ends outside this element.

function onTapCancel(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onTapCancel={onTapCancel} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: TapInfo

An TapInfo object containing x and y values for the point relative to the device or page.

#Pan

The pan gesture recognises when a pointer presses down on a component and moves further than 3 pixels. The pan gesture is ended when the pointer is released.

<motion.div onPan={(e, pointInfo) => {}} />

#onPan(event, info): void

Callback function that fires when the pan gesture is recognised on this element.

function onPan(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPan={onPan} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: PanInfo

A PanInfo object containing x and y values for:

  • point: Relative to the device or page.
  • delta: Distance moved since the last event.
  • offset: Offset from the original pan event.
  • velocity: Current velocity of the pointer.

#onPanStart(event, info): void

Callback function that fires when the pan gesture begins on this element.

function onPanStart(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPanStart={onPanStart} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: PanInfo

A PanInfo object containing x/y values for:

  • point: Relative to the device or page.
  • delta: Distance moved since the last event.
  • offset: Offset from the original pan event.
  • velocity: Current velocity of the pointer.

#onPanEnd(event, info): void

Callback function that fires when the pan gesture ends on this element.

function onPanEnd(event, info) {
  console.log(info.point.x, info.point.y)
}

<motion.div onPanEnd={onPanEnd} />
event: MouseEvent | TouchEvent | PointerEvent

The originating pointer event.

info: PanInfo

A PanInfo object containing x/y values for:

  • point: Relative to the device or page.
  • delta: Distance moved since the last event.
  • offset: Offset from the original pan event.
  • velocity: Current velocity of the pointer.

#Drag

The drag gesture follows the rules of the pan gesture but applies pointer movement to the x and/or y axis of the component.

<motion.div drag />

#drag: boolean | "x" | "y"

Enable dragging for this element. Set to false by default. Set true to drag in both directions. Set "x" or "y" to only drag in a specific direction.

<motion.div drag="x" />

#dragConstraints: false | { top?: number; right?: number; bottom?: number; left?: number; } | RefObject<Element>

An object of optional top, left, right, bottom pixel values, beyond which dragging is constrained.

Another component can be used as drag constraints by creating a ref with React's useRef.hook. This ref should be passed to that component's ref prop and to this component's dragConstraints prop.

// In pixels
<motion.div
  drag="x"
  dragConstraints={{ left: 0, right: 300 }}
/>

// As a ref to another component
const MyComponent = () => {
  const constraintsRef = useRef(null)

  return (
     <motion.div ref={constraintsRef}>
         <motion.div drag dragConstraints={constraintsRef} />
     </motion.div>
  )
}

#dragElastic: boolean | number

The degree of movement allowed outside constraints. 0 = no movement, 1 = full movement. Set to 0.5 by default.

<motion.div
  drag
  dragConstraints={{ left: 0, right: 300 }}
  dragElastic={0.2}
/>

#dragMomentum: boolean

Apply momentum from the pan gesture to the component when dragging finishes. Set to true by default.

<motion.div
  drag
  dragConstraints={{ left: 0, right: 300 }}
  dragMomentum={false}
/>

#dragTransition: InertiaOptions

Allows you to change dragging inertia parameters. When releasing a draggable Frame, an animation with type inertia starts. The animation is based on your dragging velocity. This property allows you to customize it. See Inertia for all properties you can use.

<motion.div
  drag
  dragTransition={{ bounceStiffness: 600, bounceDamping: 10 }}
/>

#dragPropagation: boolean

Allows drag gesture propagation to child components. Set to false by default.

<motion.div drag="x" dragPropagation />

#onDrag(event, info): void

Callback function that fires when the component is dragged.

<motion.div
  drag
  onDrag={
    (event, info) => console.log(info.point.x, info.point.y)
  }
/>
event: MouseEvent | TouchEvent | PointerEvent
info: PanInfo

#onDragStart(event, info): void

Callback function that fires when dragging starts.

<motion.div
  drag
  onDragStart={
    (event, info) => console.log(info.point.x, info.point.y)
  }
/>
event: MouseEvent | TouchEvent | PointerEvent
info: PanInfo

#onDragEnd(event, info): void

Callback function that fires when dragging ends.

<motion.div
  drag
  onDragEnd={
    (event, info) => console.log(info.point.x, info.point.y)
  }
/>
event: MouseEvent | TouchEvent | PointerEvent
info: PanInfo

#onDirectionLock(axis): void

Callback function that fires a drag direction is determined.

<motion.div
  drag
  dragDirectionLock
  onDirectionLock={axis => console.log(axis)}
/>
axis: "x" | "y"