# useMove



## API

<FunctionAPI
  function={docs.exports.useMove}
  links={docs.links}
/>

## Features

Move events are fired as the pointer moves around, and specify the distance that the pointer traveled since the last event. In addition, after a user focuses the target element, move events are fired when the user presses the arrow keys.

* Handles mouse and touch events
* Handles arrow key presses
* Uses pointer events where available, with fallbacks to mouse and touch events
* Ignores emulated mouse events in mobile browsers
* Handles disabling text selection on mobile while the press interaction is active
* Normalizes many cross browser inconsistencies

## Example

This example shows a ball that can be moved by dragging with a mouse or touch, or by tabbing to it and using
the arrow keys on your keyboard. The movement is clamped so that the ball cannot be dragged outside a box.
All of the move events are logged below so that you can inspect what is going on.

```tsx
import React from 'react';
import {useMove} from '@react-aria/interactions';

function Example() {
  const CONTAINER_SIZE = 200;
  const BALL_SIZE = 30;

  let [events, setEvents] = React.useState([]);
  let [color, setColor] = React.useState('black');
  let [position, setPosition] = React.useState({
    x: 0,
    y: 0
  });

  let clamp = pos => Math.min(Math.max(pos, 0), CONTAINER_SIZE - BALL_SIZE);
  let {moveProps} = useMove({
    onMoveStart(e) {
      setColor('red');
      setEvents(events => [`move start with pointerType = ${e.pointerType}`, ...events]);
    },
    onMove(e) {
      setPosition(({x, y}) => {
        // Normally, we want to allow the user to continue
        // dragging outside the box such that they need to
        // drag back over the ball again before it moves.
        // This is handled below by clamping during render.
        // If using the keyboard, however, we need to clamp
        // here so that dragging outside the container and
        // then using the arrow keys works as expected.
        if (e.pointerType === 'keyboard') {
          x = clamp(x);
          y = clamp(y);
        }

        x += e.deltaX;
        y += e.deltaY;
        return {x, y};
      });

      setEvents(events => [`move with pointerType = ${e.pointerType}, deltaX = ${e.deltaX}, deltaY = ${e.deltaY}`, ...events]);
    },
    onMoveEnd(e) {
      setPosition(({x, y}) => {
        // Clamp position on mouse up
        x = clamp(x);
        y = clamp(y);
        return {x, y};
      });
      setColor('black');
      setEvents(events => [`move end with pointerType = ${e.pointerType}`, ...events]);
    }
  });

  return (
    <>
      <div
        style={{
          width: CONTAINER_SIZE,
          height: CONTAINER_SIZE,
          background: 'white',
          border: '1px solid black',
          position: 'relative',
          touchAction: 'none'
        }}>
        <div
          {...moveProps}
          tabIndex={0}
          style={{
            width: BALL_SIZE,
            height: BALL_SIZE,
            borderRadius: '100%',
            position: 'absolute',
            left: clamp(position.x),
            top: clamp(position.y),
            background: color
          }} />
      </div>
      <ul
        style={{
          maxHeight: '200px',
          overflow: 'auto'
        }}>
        {events.map((e, i) => <li key={i}>{e}</li>)}
      </ul>
    </>
  );
}
```

## API

<FunctionAPI
  function={docs.exports.useMove}
  links={docs.links}
/>

### MoveEvents

### MoveResult

| Name | Type | Description |
|------|------|-------------|
| `moveProps` \* | `DOMAttributes<FocusableElement>` | Props to spread on the target element. |

### MoveEvent

Each of these handlers is fired with a `MoveEvent`, which exposes information about the target and the
type of event that triggered the interaction.
