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

1onTapGesture?: (() => void) | {
2  count: number
3  perform: () => void
4}

Parameters

Name Type Default Description
count number 1 Number of taps required (1 for single tap, 2 for double tap)
perform () => void Action to perform when the tap is recognized

Examples

1// Single tap
2<VStack onTapGesture={() => console.log('Tapped')} />
3
4// Double tap
5<HStack
6  onTapGesture={{
7    count: 2,
8    perform: () => console.log('Double tapped')
9  }}
10/>

onLongPressGesture

Executes an action when a long press gesture is recognized.

Type

1onLongPressGesture?: (() => void) | {
2  minDuration?: number
3  maxDuration?: number
4  perform: () => void
5  onPressingChanged?: (state: boolean) => void
6}

Parameters

Name Type Default Description
minDuration number 500 Minimum press duration (ms) before the gesture succeeds
maxDuration number 10000 Maximum duration before the gesture fails (ms)
perform () => void Action to execute when the long press succeeds
onPressingChanged (state: boolean) => void Called when pressing starts or ends (true = pressing)

Examples

1// Simple usage
2<VStack onLongPressGesture={() => console.log('Long pressed')} />
3
4// Custom duration and press state callback
5<HStack
6  onLongPressGesture={{
7    minDuration: 800,
8    maxDuration: 3000,
9    perform: () => console.log('Long press success'),
10    onPressingChanged: isPressing =>
11      console.log(isPressing ? 'Pressing...' : 'Released')
12  }}
13/>

onDragGesture

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

Type

1onDragGesture?: {
2  minDistance?: number
3  coordinateSpace?: 'local' | 'global'
4  onChanged?: (details: DragGestureDetails) => void
5  onEnded?: (details: DragGestureDetails) => void
6}

Parameters

Name Type Default Description
minDistance number 10 Minimum movement (in points) before the gesture starts
coordinateSpace 'local' 'global' 'local'
onChanged (details: DragGestureDetails) => void Called as the drag changes
onEnded (details: DragGestureDetails) => void Called when the drag ends

DragGestureDetails

1type DragGestureDetails = {
2  time: number
3  location: Point
4  startLocation: Point
5  translation: Size
6  velocity: Size
7  predictedEndLocation: Point
8  predictedEndTranslation: Size
9}
Field Description
time Timestamp of the drag event (ms)
location Current pointer position {x, y}
startLocation Initial drag position
translation Offset from start to current position
velocity Current velocity in points per second
predictedEndLocation Predicted end position based on velocity
predictedEndTranslation Predicted total translation

Example

1<VStack
2  onDragGesture={{
3    minDistance: 5,
4    coordinateSpace: 'global',
5    onChanged: details => {
6      console.log('Location:', details.location)
7      console.log('Offset:', details.translation)
8    },
9    onEnded: details => {
10      console.log('Predicted end:', details.predictedEndLocation)
11    }
12  }}
13/>

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.

1class GestureInfo<Options, Value> {
2  type: string
3  options: Options
4  onChanged(callback: (value: Value) => void): this
5  onEnded(callback: (value: Value) => void): this
6}
Method Description
onChanged(callback) Called when the gesture changes (e.g. dragging, zooming)
onEnded(callback) Called when the gesture finishes

Example

1<Text
2  gesture={
3    TapGesture()
4      .onEnded(() => console.log('Tapped'))
5  }
6/>

TapGesture

Detects single or multiple taps.

1declare function TapGesture(count?: number): GestureInfo<number | undefined, void>
Parameter Type Default Description
count number 1 Number of taps required

Example

1<Text
2  gesture={
3    TapGesture(2)
4      .onEnded(() => console.log('Double tapped'))
5  }
6/>

LongPressGesture

Detects press and hold gestures.

1declare function LongPressGesture(options?: LongPressGestureOptions): GestureInfo<LongPressGestureOptions, boolean>
2
3type LongPressGestureOptions = {
4  minDuration?: number
5  maxDuration?: number
6}
Parameter Default Description
minDuration 500 Minimum press duration (ms)
maxDuration 10000 Maximum duration before failure (ms)

Example

1<Text
2  gesture={
3    LongPressGesture({ minDuration: 800 })
4      .onChanged(() => console.log('Pressing...'))
5      .onEnded(() => console.log('Long press finished'))
6  }
7/>

DragGesture

Tracks finger or pointer movement.

1declare function DragGesture(options?: DragGestureOptions): GestureInfo<DragGestureOptions, DragGestureDetails>
2
3type DragGestureOptions = {
4  minDistance?: number
5  coordinateSpace?: 'local' | 'global'
6}

Example

1<VStack
2  gesture={
3    DragGesture({ coordinateSpace: 'global' })
4      .onChanged(d => console.log('Offset', d.translation))
5      .onEnded(d => console.log('Velocity', d.velocity))
6  }
7/>

MagnifyGesture

Detects pinch zoom gestures.

1declare function MagnifyGesture(minScaleDelta?: number | null): GestureInfo<number | null | undefined, MagnifyGestureValue>
2
3type MagnifyGestureValue = {
4  time: Date
5  magnification: number
6  startAnchor: Point
7  startLocation: Point
8  velocity: number
9}

Example

1<Text
2  gesture={
3    MagnifyGesture(0.05)
4      .onChanged(v => console.log('Scale', v.magnification))
5      .onEnded(() => console.log('Zoom ended'))
6  }
7/>

RotateGesture

Detects rotation gestures.

1declare function RotateGesture(minAngleDelta?: Angle | null): GestureInfo<Angle | null | undefined, RotateGestureValue>
2
3type RotateGestureValue = {
4  rotation: AngleValue
5  velocity: AngleValue
6  startAnchor: Point
7  time: Date
8}
9
10type AngleValue = {
11  radians: number
12  degrees: number
13  magnitude: number
14  animatableData: number
15}

Example

1<ZStack
2  gesture={
3    RotateGesture()
4      .onChanged(v => console.log('Rotation', v.rotation.degrees))
5      .onEnded(() => console.log('Rotation ended'))
6  }
7/>

3. Gesture Modifiers for Views

All views support the following gesture-related properties.

1type GesturesProps = {
2  gesture?: GestureProps
3  simultaneousGesture?: GestureProps
4  highPriorityGesture?: GestureProps
5  defersSystemGestures?: EdgeSet
6}

gesture

Adds a gesture to the view.

1<Text
2  gesture={
3    TapGesture()
4      .onEnded(() => console.log('Tapped'))
5  }
6/>

highPriorityGesture

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

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

simultaneousGesture

Allows multiple gestures to be recognized simultaneously.

1<Text
2  simultaneousGesture={
3    LongPressGesture()
4      .onEnded(() => console.log('Long pressed'))
5  }
6  gesture={
7    TapGesture()
8      .onEnded(() => console.log('Tapped'))
9  }
10/>

defersSystemGestures

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

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

Accepted Values

Value Description
'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.

1type GestureMask = "all" | "gesture" | "subviews" | "none"
Value Description
"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

1<VStack
2  gesture={{
3    gesture: TapGesture().onEnded(() => console.log('Tapped')),
4    mask: 'gesture'
5  }}
6>
7  <Text>Tap here</Text>
8</VStack>

5. Summary Table

Gesture Type Description Class Constructor Shorthand Property Common Callbacks
Tap Detects single or multiple taps TapGesture() onTapGesture .onEnded()
Long Press Detects hold gestures LongPressGesture() onLongPressGesture .onChanged(), .onEnded()
Drag Detects movement DragGesture() onDragGesture .onChanged(), .onEnded()
Magnify Detects pinch zoom MagnifyGesture() .onChanged(), .onEnded()
Rotate Detects rotation RotateGesture() .onChanged(), .onEnded()