Gestures

The Scripting app provides a gesture system similar to SwiftUI, allowing any view (<VStack>, <HStack>, <Text>, etc.) to respond to touch interactions such as tapping, long pressing, dragging, rotating, and magnifying.

You can use:

  • Simplified gesture properties like onTapGesture, onLongPressGesture, onDragGesture, or
  • Advanced gesture objects such as TapGesture(), LongPressGesture(), and the gesture modifiers for composition and priority control.

1. Simple Gesture Properties

These are convenient, shorthand ways to add gestures directly to a view.


onTapGesture

Executes an action when a tap gesture is recognized.

Type

onTapGesture?: (() => void) | {
  count: number
  perform: () => void
}

Parameters

NameTypeDefaultDescription
countnumber1Number of taps required (1 for single tap, 2 for double tap)
perform() => voidAction to perform when the tap is recognized

Examples

// Single tap
<VStack onTapGesture={() => console.log('Tapped')} />

// Double tap
<HStack
  onTapGesture={{
    count: 2,
    perform: () => console.log('Double tapped')
  }}
/>

onLongPressGesture

Executes an action when a long press gesture is recognized.

Type

onLongPressGesture?: (() => void) | {
  minDuration?: number
  maxDuration?: number
  perform: () => void
  onPressingChanged?: (state: boolean) => void
}

Parameters

NameTypeDefaultDescription
minDurationnumber500Minimum press duration (ms) before the gesture succeeds
maxDurationnumber10000Maximum duration before the gesture fails (ms)
perform() => voidAction to execute when the long press succeeds
onPressingChanged(state: boolean) => voidCalled when pressing starts or ends (true = pressing)

Examples

// Simple usage
<VStack onLongPressGesture={() => console.log('Long pressed')} />

// Custom duration and press state callback
<HStack
  onLongPressGesture={{
    minDuration: 800,
    maxDuration: 3000,
    perform: () => console.log('Long press success'),
    onPressingChanged: isPressing =>
      console.log(isPressing ? 'Pressing...' : 'Released')
  }}
/>

onDragGesture

Adds a drag gesture to a view, tracking position, offset, and velocity.

Type

onDragGesture?: {
  minDistance?: number
  coordinateSpace?: 'local' | 'global'
  onChanged?: (details: DragGestureDetails) => void
  onEnded?: (details: DragGestureDetails) => void
}

Parameters

NameTypeDefaultDescription
minDistancenumber10Minimum movement (in points) before the gesture starts
coordinateSpace'local''global''local'
onChanged(details: DragGestureDetails) => voidCalled as the drag changes
onEnded(details: DragGestureDetails) => voidCalled when the drag ends

DragGestureDetails

type DragGestureDetails = {
  time: number
  location: Point
  startLocation: Point
  translation: Size
  velocity: Size
  predictedEndLocation: Point
  predictedEndTranslation: Size
}
FieldDescription
timeTimestamp of the drag event (ms)
locationCurrent pointer position {x, y}
startLocationInitial drag position
translationOffset from start to current position
velocityCurrent velocity in points per second
predictedEndLocationPredicted end position based on velocity
predictedEndTranslationPredicted total translation

Example

<VStack
  onDragGesture={{
    minDistance: 5,
    coordinateSpace: 'global',
    onChanged: details => {
      console.log('Location:', details.location)
      console.log('Offset:', details.translation)
    },
    onEnded: details => {
      console.log('Predicted end:', details.predictedEndLocation)
    }
  }}
/>

2. Gesture Classes (Advanced Usage)

For complex interaction handling or gesture composition, use the gesture constructors and modifiers.


GestureInfo Class

All gesture constructors return a GestureInfo object that defines configuration and callbacks.

class GestureInfo<Options, Value> {
  type: string
  options: Options
  onChanged(callback: (value: Value) => void): this
  onEnded(callback: (value: Value) => void): this
}
MethodDescription
onChanged(callback)Called when the gesture changes (e.g. dragging, zooming)
onEnded(callback)Called when the gesture finishes

Example

<Text
  gesture={
    TapGesture()
      .onEnded(() => console.log('Tapped'))
  }
/>

TapGesture

Detects single or multiple taps.

declare function TapGesture(count?: number): GestureInfo<number | undefined, void>
ParameterTypeDefaultDescription
countnumber1Number of taps required

Example

<Text
  gesture={
    TapGesture(2)
      .onEnded(() => console.log('Double tapped'))
  }
/>

LongPressGesture

Detects press and hold gestures.

declare function LongPressGesture(options?: LongPressGestureOptions): GestureInfo<LongPressGestureOptions, boolean>

type LongPressGestureOptions = {
  minDuration?: number
  maxDuration?: number
}
ParameterDefaultDescription
minDuration500Minimum press duration (ms)
maxDuration10000Maximum duration before failure (ms)

Example

<Text
  gesture={
    LongPressGesture({ minDuration: 800 })
      .onChanged(() => console.log('Pressing...'))
      .onEnded(() => console.log('Long press finished'))
  }
/>

DragGesture

Tracks finger or pointer movement.

declare function DragGesture(options?: DragGestureOptions): GestureInfo<DragGestureOptions, DragGestureDetails>

type DragGestureOptions = {
  minDistance?: number
  coordinateSpace?: 'local' | 'global'
}

Example

<VStack
  gesture={
    DragGesture({ coordinateSpace: 'global' })
      .onChanged(d => console.log('Offset', d.translation))
      .onEnded(d => console.log('Velocity', d.velocity))
  }
/>

MagnifyGesture

Detects pinch zoom gestures.

declare function MagnifyGesture(minScaleDelta?: number | null): GestureInfo<number | null | undefined, MagnifyGestureValue>

type MagnifyGestureValue = {
  time: Date
  magnification: number
  startAnchor: Point
  startLocation: Point
  velocity: number
}

Example

<Text
  gesture={
    MagnifyGesture(0.05)
      .onChanged(v => console.log('Scale', v.magnification))
      .onEnded(() => console.log('Zoom ended'))
  }
/>

RotateGesture

Detects rotation gestures.

declare function RotateGesture(minAngleDelta?: Angle | null): GestureInfo<Angle | null | undefined, RotateGestureValue>

type RotateGestureValue = {
  rotation: AngleValue
  velocity: AngleValue
  startAnchor: Point
  time: Date
}

type AngleValue = {
  radians: number
  degrees: number
  magnitude: number
  animatableData: number
}

Example

<ZStack
  gesture={
    RotateGesture()
      .onChanged(v => console.log('Rotation', v.rotation.degrees))
      .onEnded(() => console.log('Rotation ended'))
  }
/>

3. Gesture Modifiers for Views

All views support the following gesture-related properties.

type GesturesProps = {
  gesture?: GestureProps
  simultaneousGesture?: GestureProps
  highPriorityGesture?: GestureProps
  defersSystemGestures?: EdgeSet
}

gesture

Adds a gesture to the view.

<Text
  gesture={
    TapGesture()
      .onEnded(() => console.log('Tapped'))
  }
/>

highPriorityGesture

Adds a gesture with higher priority than existing ones on the view.

<Text
  highPriorityGesture={
    TapGesture(2)
      .onEnded(() => console.log('Double tap takes priority'))
  }
/>

simultaneousGesture

Allows multiple gestures to be recognized simultaneously.

<Text
  simultaneousGesture={
    LongPressGesture()
      .onEnded(() => console.log('Long pressed'))
  }
  gesture={
    TapGesture()
      .onEnded(() => console.log('Tapped'))
  }
/>

defersSystemGestures

Gives your custom gestures precedence over system gestures originating from screen edges.

<VStack defersSystemGestures="all">
  <Text>Custom gestures take precedence</Text>
</VStack>

Accepted Values

ValueDescription
'top'Top edge
'leading'Leading edge (left, or right in RTL)
'trailing'Trailing edge
'bottom'Bottom edge
'horizontal'Left and right edges
'vertical'Top and bottom edges
'all'All edges

4. GestureMask

Controls how adding a gesture affects other gestures on the same view or its subviews.

type GestureMask = "all" | "gesture" | "subviews" | "none"
ValueDescription
"all"Enables both the added gesture and subview gestures (default)
"gesture"Enables only the added gesture, disables subview gestures
"subviews"Enables subview gestures, disables the added gesture
"none"Disables all gestures

Example

<VStack
  gesture={{
    gesture: TapGesture().onEnded(() => console.log('Tapped')),
    mask: 'gesture'
  }}
>
  <Text>Tap here</Text>
</VStack>

5. Summary Table

Gesture TypeDescriptionClass ConstructorShorthand PropertyCommon Callbacks
TapDetects single or multiple tapsTapGesture()onTapGesture.onEnded()
Long PressDetects hold gesturesLongPressGesture()onLongPressGesture.onChanged(), .onEnded()
DragDetects movementDragGesture()onDragGesture.onChanged(), .onEnded()
MagnifyDetects pinch zoomMagnifyGesture().onChanged(), .onEnded()
RotateDetects rotationRotateGesture().onChanged(), .onEnded()