> ## Documentation Index
> Fetch the complete documentation index at: https://docs.napps.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Gesture detector

`gestureDetector` adds native gesture recognition around a subtree. It is experimental and may
change in a future runtime.

## Properties

| Property     | Accepted value                                             | Description                               |
| ------------ | ---------------------------------------------------------- | ----------------------------------------- |
| `enabled`    | `boolean`                                                  | Enables gesture recognition.              |
| `gesture`    | `"pan" \| "tap" \| "longPress" \| "drag" \| GestureConfig` | Gesture kind or configured gesture.       |
| `onBegin`    | `(event: GestureEvent) => void`                            | Called when recognition begins.           |
| `onStart`    | `(event: GestureEvent) => void`                            | Called when the gesture activates.        |
| `onUpdate`   | `(event: GestureEvent) => void`                            | Called while the gesture changes.         |
| `onEnd`      | `(event: GestureEvent) => void`                            | Called when it ends normally.             |
| `onCancel`   | `(event: GestureEvent) => void`                            | Called when recognition is cancelled.     |
| `onFinalize` | `(event: GestureEvent) => void`                            | Called after completion or cancellation.  |
| `style`      | `StyleProperties`                                          | Layout and appearance values.             |
| `children`   | `ReactNode`                                                | Subtree receiving gesture handling.       |
| `key`        | `string \| number`                                         | React key for dynamic detectors.          |
| `class`      | `string`                                                   | Registered style name for this node only. |

```ts theme={null}
interface GestureConfig {
  type?: "pan" | "tap" | "longPress" | "drag";
  maxDistance?: number;
  minDistance?: number;
}

interface GestureEvent {
  state: "began" | "active" | "ended" | "cancelled";
  x: number;
  y: number;
  absoluteX: number;
  absoluteY: number;
  translationX: number;
  translationY: number;
  velocityX: number;
  velocityY: number;
  pointerCount: number;
  timestamp: number;
}
```

## Tap

Use `tap` for a completed press with limited pointer movement. Restore temporary feedback from
`onFinalize`, which also runs when the gesture is cancelled.

```tsx theme={null}
const scale = sv(1);

<gestureDetector
  gesture={{ type: "tap", maxDistance: 12 }}
  onBegin={() => {
    scale.value = timing(0.96, { duration: 80 });
  }}
  onFinalize={() => {
    scale.value = timing(1, { duration: 120 });
  }}
>
  <box
    style={animatedProps({
      scale,
      width: 160,
      height: 48,
      borderRadius: 12,
      backgroundColor: "#2563eb"
    })}
  >
    <text style={{ color: "#ffffff", textAlignment: "center" }}>Add to cart</text>
  </box>
</gestureDetector>
```

## Pan

Use `pan` when movement should update the UI continuously. `mapEvent` copies gesture values into
shared values without a React render on every pointer update.

```tsx theme={null}
const offsetX = sv(0);

<gestureDetector
  gesture={{ type: "pan", minDistance: 8 }}
  onUpdate={mapEvent({ translationX: offsetX })}
  onEnd={(event) => {
    offsetX.value = spring(0, { velocity: event.velocityX });
  }}
>
  <box
    style={animatedProps({
      translationX: offsetX,
      width: 180,
      height: 100,
      borderRadius: 16,
      backgroundColor: "#dbeafe"
    })}
  />
</gestureDetector>
```

## Long press

Use `longPress` for hold actions. `onStart` runs after the native long-press threshold is reached.

```tsx theme={null}
const alpha = sv(0.7);

<gestureDetector
  gesture={{ type: "longPress", maxDistance: 16 }}
  onStart={() => {
    alpha.value = timing(1, { duration: 120 });
  }}
  onFinalize={() => {
    alpha.value = timing(0.7, { duration: 120 });
  }}
>
  <box
    style={animatedProps({
      alpha,
      width: 180,
      height: 56,
      borderRadius: 12,
      backgroundColor: "#f59e0b"
    })}
  >
    <text style={{ textAlignment: "center" }}>Hold for options</text>
  </box>
</gestureDetector>
```

## Drag

`drag` is an alias for the native pan implementation. Use it when the UI represents a draggable
object; its lifecycle and event data match `pan`.

```tsx theme={null}
const offsetY = sv(0);

<gestureDetector
  gesture={{ type: "drag", minDistance: 8 }}
  onUpdate={mapEvent({ translationY: offsetY })}
  onEnd={(event) => {
    offsetY.value = spring(0, { velocity: event.velocityY });
  }}
>
  <box
    style={animatedProps({
      translationY: offsetY,
      width: 180,
      height: 100,
      borderRadius: 16,
      backgroundColor: "#dbeafe"
    })}
  >
    <text style={{ textAlignment: "center" }}>Drag me</text>
  </box>
</gestureDetector>
```

Use `mapEvent` for high-frequency gesture updates and a callback when you need custom logic. See
[React gestures](/js-ui/react/gestures) for cancellation and animation patterns.
