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/>
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() |