Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
4e3e30f
Pan gesture
m-bert Dec 9, 2025
7ac164d
Merge branch 'next' into @mbert/docs-v3
m-bert Dec 10, 2025
203131e
Finish (?) Pan
m-bert Dec 10, 2025
db99336
Tap
m-bert Dec 10, 2025
f01bd66
Long press
m-bert Dec 10, 2025
5490439
Rotation
m-bert Dec 10, 2025
ded8083
Pinch
m-bert Dec 10, 2025
e38591c
Fling
m-bert Dec 10, 2025
f338fa7
Hover
m-bert Dec 10, 2025
11c91a7
Native
m-bert Dec 10, 2025
37d7438
Manual
m-bert Dec 10, 2025
a93970a
Fix path
m-bert Dec 10, 2025
d23e66b
Remove cache from workflow
m-bert Dec 10, 2025
5c0b717
composition
m-bert Dec 11, 2025
f293949
Remove PanHandlerData
m-bert Dec 15, 2025
34a93a5
Use correct HandlerData
m-bert Dec 15, 2025
f4847dc
Merge branch 'next' into @mbert/docs-v3
m-bert Dec 15, 2025
87a1130
Merge branch 'next' into @mbert/docs-v3
m-bert Dec 16, 2025
b96d788
Bye bye API 2
m-bert Dec 16, 2025
cf3f810
Fix hover
m-bert Dec 16, 2025
944d689
Fix old links
m-bert Dec 16, 2025
d2958e0
Another links
m-bert Dec 16, 2025
d8eaaeb
remove useless prop
m-bert Dec 22, 2025
b2a373e
Add warning to requireToFail
m-bert Dec 22, 2025
d3c7893
One composition
m-bert Dec 22, 2025
e96349e
Remove outdated info
m-bert Dec 22, 2025
cd7c0d6
Remove SharedValue notes
m-bert Dec 22, 2025
ca2d46a
rephrase exclusive
m-bert Dec 22, 2025
1811c9c
Other composition updates
m-bert Dec 22, 2025
4fa234f
Change reference to example
m-bert Dec 22, 2025
fb8e2ef
Change reference to example yet again (manual)
m-bert Dec 22, 2025
47da2df
Tapp
m-bert Dec 22, 2025
c8a4a76
Native on web
m-bert Dec 22, 2025
5c3d918
Add missing pan properties
m-bert Dec 22, 2025
a8c6ccc
Simplify pinch example
m-bert Dec 22, 2025
421d247
scaleChange
m-bert Dec 22, 2025
b14eadf
Add pan headers
m-bert Dec 22, 2025
b769862
Rotation gesture changes
m-bert Dec 22, 2025
49b1d3e
Test id correct prop name
m-bert Dec 22, 2025
41f7a4f
Add SharedValue info
m-bert Dec 22, 2025
1fb9b51
Add missing shared value info to long press
m-bert Dec 22, 2025
6d2da5a
Remove secondary headers
m-bert Dec 22, 2025
f90b378
Change order
m-bert Dec 22, 2025
b4cd005
Merge branch 'next' into @mbert/docs-detector
m-bert Dec 23, 2025
5255e4a
Detecor page
m-bert Dec 23, 2025
205c0a8
Gesture detector
m-bert Dec 23, 2025
4c53b94
Change ordering
m-bert Dec 23, 2025
c4d44dc
Update quickstart
m-bert Dec 23, 2025
42b04b1
Update links
m-bert Dec 23, 2025
45f5bc6
Merge branch '@mbert/docs-detector' into @mbert/docs-quick-start
m-bert Dec 23, 2025
03501dc
Other links
m-bert Dec 23, 2025
2f008cd
Merge branch '@mbert/docs-detector' into @mbert/docs-quick-start
m-bert Dec 23, 2025
e1fae87
Merge branch 'next' into @mbert/docs-detector
m-bert Jan 7, 2026
59fd8df
Merge branch 'next' into @mbert/docs-detector
m-bert Jan 9, 2026
1b930d5
Merge branch '@mbert/docs-detector' into @mbert/docs-quick-start
m-bert Jan 9, 2026
c3d0441
Merge 2 steps
m-bert Jan 13, 2026
eccaa37
Better phrasing
m-bert Jan 13, 2026
c82771e
Explain SharedValue earlier
m-bert Jan 14, 2026
f3dd311
Link to reanimated
m-bert Jan 14, 2026
7b9317b
Update guide
m-bert Jan 20, 2026
8e925d1
Merge branch 'next' into @mbert/docs-quick-start
m-bert Jan 28, 2026
e7c3d39
Add theme common to package.json
m-bert Jan 28, 2026
c4db823
Remove duplicate detector entry
m-bert Jan 28, 2026
bd65d21
Undo formatting
m-bert Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
```jsx
import { StyleSheet } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';

export default function Ball() {
return (
<GestureHandlerRootView>
<Animated.View style={styles.ball} />
</GestureHandlerRootView>
);
}

const styles = StyleSheet.create({
ball: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,25 @@
```jsx
import { GestureDetector } from 'react-native-gesture-handler';
import Animated from 'react-native-reanimated';
import {
useAnimatedStyle,
useSharedValue,
withSpring,
} from 'react-native-reanimated';

function Ball() {
return (
<GestureDetector>
<Animated.View style={[styles.ball]} />
</GestureDetector>
);
export default function Ball() {
const isPressed = useSharedValue(false);
const offset = useSharedValue({ x: 0, y: 0 });

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [
{ translateX: offset.value.x },
{ translateY: offset.value.y },
{ scale: withSpring(isPressed.value ? 1.2 : 1) },
],
backgroundColor: isPressed.value ? 'yellow' : 'blue',
};
});

// ...
}
```
Original file line number Diff line number Diff line change
@@ -1,25 +1,9 @@
```jsx
import {
useSharedValue,
useAnimatedStyle,
withSpring,
} from 'react-native-reanimated';

function Ball() {
const isPressed = useSharedValue(false);
const offset = useSharedValue({ x: 0, y: 0 });

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [
{ translateX: offset.value.x },
{ translateY: offset.value.y },
{ scale: withSpring(isPressed.value ? 1.2 : 1) },
],
backgroundColor: isPressed.value ? 'yellow' : 'blue',
};
});

// ...
}
```jsx {4}
// ...
return (
<GestureHandlerRootView>
<Animated.View style={[styles.ball, animatedStyles]} />
</GestureHandlerRootView>
);
// ...
```
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
```jsx {4}
// ...
return (
<GestureDetector>
<Animated.View style={[styles.ball, animatedStyles]} />
</GestureDetector>
);
// ...
```jsx
import { usePanGesture } from 'react-native-gesture-handler';

function Ball() {
// ...
const gesture = usePanGesture({
onBegin: () => {
isPressed.value = true;
},
onUpdate: (e) => {
offset.value = {
x: offset.value.x + e.changeX,
y: offset.value.y + e.changeY,
};
},
onFinalize: () => {
isPressed.value = false;
},
});
// ...
}
```
Original file line number Diff line number Diff line change
@@ -1,38 +1,11 @@
```jsx
import { Gesture } from 'react-native-gesture-handler';

function Ball() {
// ...
const start = useSharedValue({ x: 0, y: 0 });
const gesture = Gesture.Pan()
.onBegin(() => {
isPressed.value = true;
})
.onUpdate((e) => {
offset.value = {
x: e.translationX + start.value.x,
y: e.translationY + start.value.y,
};
})
.onEnd(() => {
start.value = {
x: offset.value.x,
y: offset.value.y,
};
})
.onFinalize(() => {
isPressed.value = false;
});
// ...
}
```

```jsx {3}
```jsx {4}
// ...
return (
<GestureDetector gesture={gesture}>
<Animated.View style={[styles.ball, animatedStyles]} />
</GestureDetector>
<GestureHandlerRootView>
<GestureDetector gesture={gesture}>
<Animated.View style={[styles.ball, animatedStyles]} />
</GestureDetector>
</GestureHandlerRootView>
);
// ...
```
91 changes: 74 additions & 17 deletions packages/docs-gesture-handler/docs/guides/quickstart/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,45 +12,102 @@ import Step3 from './\_steps/step3.md';
import Step4 from './\_steps/step4.md';
import Step5 from './\_steps/step5.md';

RNGH2 provides much simpler way to add gestures to your app. All you need to do is wrap the view that you want your gesture to work on with [`GestureDetector`](/docs/fundamentals/gesture-detectors#gesture-detector), define the gesture and pass it to detector. That's all!
RNGH3 offers a straightforward way to add gestures to your app. Simply wrap your target view with the [GestureDetector](/docs/fundamentals/gesture-detectors#gesture-detector) component, define your gesture, and pass it in. That’s it!

To demonstrate how you would use the new API, let's make a simple app where you can drag a ball around. You will need to add `react-native-gesture-handler` (for gestures) and `react-native-reanimated` (for animations) modules.
To see the new API in action, let's build a simple app where you can drag a ball around the screen. To follow along, you'll need both `react-native-gesture-handler` (to handle gestures) and [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/) (to handle the animations).

<Step title="Step 1">
<div>First let's define styles we will need to make the app:</div>
<div>Start by defining the basic structure of the application:</div>
<Step1 />
</Step>

<Step title="Step 2">
<div>Then we can start writing our <code>Ball</code> component:</div>
<div>
Next, define the <a href="https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary#shared-value">`SharedValues`</a> to track the ball's position and create the animated styles required to position the ball on the screen:
</div>
<Step2 />
</Step>

<Step title="Step 3">
<div>
We also need to define{' '}
<a href="https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/glossary#shared-value">
shared values
</a>{' '}
to keep track of the ball position and create animated styles in order to be
able to position the ball on the screen:
</div>
<div>Apply the animated styles to the ball component:</div>
<Step3 />
</Step>

<Step title="Step 4">
<div>And add it to the ball's styles:</div>
<div>
Now, define the <code>Pan</code> gesture logic.
</div>
<Step4 />
</Step>

<Step title="Step 5">
<div>
The only thing left is to define the pan gesture and assign it to the
detector:
Finally, wrap the component responsible for rendering the ball with a <code>GestureDetector</code>, and attach the <code>Pan</code> gesture to it:
</div>
<Step5 />
</Step>

Note the `start` shared value. We need it to store the position of the ball at the moment we grab it to be able to correctly position it later, because we only have access to translation relative to the starting point of the gesture.
The complete implementation is shown below:

```jsx
import { StyleSheet } from 'react-native';
import {
GestureDetector,
GestureHandlerRootView,
usePanGesture,
} from 'react-native-gesture-handler';
import Animated, {
useAnimatedStyle,
useSharedValue,
withSpring,
} from 'react-native-reanimated';

export default function Ball() {
const isPressed = useSharedValue(false);
const offset = useSharedValue({ x: 0, y: 0 });

const gesture = usePanGesture({
onBegin: () => {
isPressed.value = true;
},
onUpdate: (e) => {
offset.value = {
x: offset.value.x + e.changeX,
y: offset.value.y + e.changeY,
};
},
onFinalize: () => {
isPressed.value = false;
},
});

const animatedStyles = useAnimatedStyle(() => {
return {
transform: [
{ translateX: offset.value.x },
{ translateY: offset.value.y },
{ scale: withSpring(isPressed.value ? 1.2 : 1) },
],
backgroundColor: isPressed.value ? 'yellow' : 'blue',
};
});

return (
<GestureHandlerRootView>
<GestureDetector gesture={gesture}>
<Animated.View style={[styles.ball, animatedStyles]} />
</GestureDetector>
</GestureHandlerRootView>
);
}

Now you can just add `Ball` component to some view in the app and see the results! (Or you can just check the code [here](https://github.com/software-mansion/react-native-gesture-handler/blob/main/example/src/new_api/velocityTest/index.tsx) and see it in action in the Example app.)
const styles = StyleSheet.create({
ball: {
width: 100,
height: 100,
borderRadius: 100,
backgroundColor: 'blue',
alignSelf: 'center',
},
});
```
3 changes: 2 additions & 1 deletion packages/docs-gesture-handler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,18 @@
"@docusaurus/core": "3.7.0",
"@docusaurus/plugin-debug": "3.7.0",
"@docusaurus/preset-classic": "3.7.0",
"@docusaurus/theme-common": "3.7.0",
"@emotion/react": "^11.14.0",
"@emotion/styled": "^11.14.0",
"@mdx-js/react": "^3.0.0",
"@mui/material": "^7.1.0",
"@swmansion/t-rex-ui": "1.0.0",
"@vercel/og": "^0.6.2",
"prism-react-renderer": "^2.1.0",
"babel-polyfill": "^6.26.0",
"babel-preset-expo": "^9.2.2",
"babel-preset-react-native": "^4.0.1",
"clsx": "^2.1.0",
"prism-react-renderer": "^2.1.0",
"raf": "^3.4.1",
"raw-loader": "^4.0.2",
"react": "^18.2.0",
Expand Down