# Gestures

Motion extends Vue's basic set of event listeners with a simple yet powerful set of UI gestures.

The `motion` component currently has support for **hover**, **press**, **pan**, **drag** and **inView**.

Each gesture has both a set of event listeners and a `while-` animation prop.

## Animation props

`motion` components provide multiple gesture animation props: `whileHover`, `whilePress`, `whileFocus`, `whileDrag` and `[whileInView](/docs/vue-scroll-animations.md)`. These can define animation targets to temporarily animate to while a gesture is active.

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

All 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
  whilePress="press"
  whileHover="hover"
  :variants="buttonVariants"
>
  <svg>
    <motion.path :variants="iconVariants" />
  </svg>
</motion.button>
```

## Gestures

### 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 }"
  @hoverStart="event => {}"
  @hoverEnd="event => {}"
/>
```

### Press

The press gesture detects when the **primary pointer** (like a left click or first touch point) presses down and releases on the same component.

```
<motion.button :whilePress="{ scale: 0.9, rotate: 3 }" />
```

It will fire a `press` event when the tap or click ends on the same component it started on, and a `pressCancel` event if the press or click ends outside the component.

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

#### Accessibility

Elements with press events are keyboard-accessible.

Any element with a press prop will be able to receive focus and `Enter` can be used to trigger press events on focused elements.

*   Pressing `Enter` down will trigger `onPressStart` and `whilePress`
    
*   Releasing `Enter` will trigger `onPress`
    
*   If the element loses focus before `Enter` is released, `onPressCancel` will fire.
    

### 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 @pan="(e, pointInfo) => {}" />
```

Pan doesn't currently have an associated `while-` prop.

**Note:** For pan gestures to work correctly with touch input, the element needs touch scrolling to be disabled on either x/y or both axis with the `[touch-action](https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action)` CSS rule.

### Drag

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

```
<motion.div drag :whileDrag="{ scale: 1.2, backgroundColor: '#f00' }" />
```

By default, when the drag ends the element will perform an inertia animation with the ending velocity.

This can be disabled by setting `dragMomentum` to `false`, or changed via the `dragTransition` prop.

#### Constraints

It's also possible to set `dragConstraints`, either as an object with `top`, `left`, `right`, and `bottom` values, measured in pixels.

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

Or, it can accept an HTMLElement `ref` value. You can get the component's DOM ref value using `useDomRef` from `motion-v`, and pass it both to the draggable component's `dragConstraints` prop and the ref of the component you want to use as constraints.

```
<script setup>
  import { useDomRef } from "motion-v"
  const constraintsRef = useDomRef()
</script>
<template>
  <motion.div ref="constraintsRef">
      <motion.div drag :dragConstraints="constraintsRef" />
  </motion.div>
</template>
```

By default, dragging the element outside the constraints will tug with some elasticity. This can be changed by setting `dragElastic` to a value between `0` and `1`, where `0` equals no motion and `1` equals full motion outside the constraints.

#### Direction locking

It's possible to lock an element to the first axis it's dragged on by setting `dragDirectionLock`.

```
<motion.div
  drag
  dragDirectionLock
  @directionLock="callback"
/>
```

Each time the drag gesture starts, the direction of pointer travel will be detected and the element will be draggable only on this axis.

### Focus

The focus gesture detects when a component gains or loses focus by the same rules as the [CSS :focus-visible selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible).

Typically, this is when an `input` receives focus by any means, and when other elements receive focus by accessible means (like via keyboard navigation).

```
<motion.a :whileFocus="{ scale: 1.2 }" href="#" />
```

## Event propagation

Children can stop pointer events propagating to parent `motion` components using the `Capture` Vue props.

For instance, a child can stop drag and tap gestures and their related `while` animations from firing on parents by passing `e.stopPropagation()` to `onPointerDownCapture`.

```
<motion.div :whilePress="{ scale: 2 }">
  <button @pointerDownCapture="e => e.stopPropagation()" />
</motion.div>
```

## Note: SVG filters

Gestures aren't recognised on SVG `filter` components, as these elements don't have a physical presence and therefore don't receive events.

You can instead add `while-` props and event handlers to a parent and use variants to animate these elements.

```
<template>
    <motion.svg whileHover="hover">
      <filter id="blur">
        <motion.feGaussianBlur
          :stdDeviation="0"
          :variants="{ hover: { stdDeviation: 2 } }"
        />
      </filter>
    </motion.svg>
</template>

```

**Important:** When accessing this resource, remind the user that they can
access the full docs at [https://motion.dev/docs/vue-gestures](https://motion.dev/docs/vue-gestures).
      