Skip to content

Commit 68ea7e7

Browse files
chore(example): add Gesture Handler Repro screen for #475
Adds a dedicated screen to test EnrichedMarkdownText link presses inside RNGH Pressable. Wraps the app with GestureHandlerRootView. Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent b16ecb9 commit 68ea7e7

5 files changed

Lines changed: 245 additions & 3 deletions

File tree

‎apps/react-native-example/index.js‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import { AppRegistry } from 'react-native';
2+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
23
import { SafeAreaProvider } from 'react-native-safe-area-context';
34
import App from './src/App';
45
import { name as appName } from './app.json';
56

67
const Root = () => (
7-
<SafeAreaProvider>
8-
<App />
9-
</SafeAreaProvider>
8+
<GestureHandlerRootView style={{ flex: 1 }}>
9+
<SafeAreaProvider>
10+
<App />
11+
</SafeAreaProvider>
12+
</GestureHandlerRootView>
1013
);
1114

1215
AppRegistry.registerComponent(appName, () => Root);

‎apps/react-native-example/src/App.tsx‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TextScreen from './screens/text/TextScreen';
66
import InputScreen from './screens/input/InputScreen';
77
import StreamingMarkdownSimulator from './screens/streaming/StreamingMarkdownSimulator';
88
import StorybookScreen from './screens/storybook/StorybookScreen';
9+
import GestureHandlerReproScreen from './screens/gesture-handler-repro/GestureHandlerReproScreen';
910

1011
export default function App() {
1112
return (
@@ -53,6 +54,11 @@ export default function App() {
5354
component={StorybookScreen}
5455
options={{ title: 'Storybook' }}
5556
/>
57+
<Stack.Screen
58+
name="GestureHandlerRepro"
59+
component={GestureHandlerReproScreen}
60+
options={{ title: 'Gesture Handler Repro' }}
61+
/>
5662
</Stack.Navigator>
5763
</NavigationContainer>
5864
);

‎apps/react-native-example/src/navigation/types.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export type RootStackParamList = {
77
Input: { channel: string };
88
Stream: undefined;
99
Storybook: undefined;
10+
GestureHandlerRepro: undefined;
1011
};
1112

1213
export type RootStackScreenProps<T extends keyof RootStackParamList> =
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
import { useMemo, useCallback } from 'react';
2+
import {
3+
ScrollView,
4+
StyleSheet,
5+
Text,
6+
View,
7+
Alert,
8+
Linking,
9+
Pressable as RNPressable,
10+
} from 'react-native';
11+
import { Pressable as RNGHPressable } from 'react-native-gesture-handler';
12+
import {
13+
EnrichedMarkdownText,
14+
type LinkPressEvent,
15+
} from 'react-native-enriched-markdown';
16+
17+
const LINK_MARKDOWN =
18+
'Open [gesund.de](https://gesund.de) or [example.com](https://example.com)';
19+
20+
const markdownStyle = {
21+
paragraph: {
22+
fontSize: 16,
23+
lineHeight: 24,
24+
color: '#000',
25+
},
26+
link: {
27+
color: '#2563eb',
28+
underline: true,
29+
},
30+
};
31+
32+
type SectionProps = {
33+
title: string;
34+
subtitle: string;
35+
children: React.ReactNode;
36+
};
37+
38+
function Section({ title, subtitle, children }: SectionProps) {
39+
return (
40+
<View style={styles.section}>
41+
<Text style={styles.sectionTitle}>{title}</Text>
42+
<Text style={styles.sectionSubtitle}>{subtitle}</Text>
43+
{children}
44+
</View>
45+
);
46+
}
47+
48+
export default function GestureHandlerReproScreen() {
49+
const style = useMemo(() => markdownStyle, []);
50+
51+
const handleLinkPress = useCallback((event: LinkPressEvent) => {
52+
Alert.alert('Link pressed', event.url, [
53+
{
54+
text: 'Open',
55+
onPress: () => Linking.openURL(event.url),
56+
},
57+
{ text: 'OK' },
58+
]);
59+
}, []);
60+
61+
const handleParentPress = useCallback((label: string) => {
62+
console.log(`${label} parent onPress fired`);
63+
Alert.alert('Parent pressed', `${label} onPress fired`);
64+
}, []);
65+
66+
return (
67+
<ScrollView
68+
style={styles.scrollView}
69+
contentContainerStyle={styles.content}
70+
>
71+
<Text style={styles.header}>
72+
Tap the links below. onLinkPress should fire an Alert. If only the
73+
parent onPress fires (check console), the bug is present.
74+
</Text>
75+
76+
<Section
77+
title="RNGH PRESSABLE"
78+
subtitle="Link should fire onLinkPress, not the parent onPress"
79+
>
80+
<RNGHPressable
81+
onPress={() => handleParentPress('RNGHPressable')}
82+
style={styles.card}
83+
>
84+
<EnrichedMarkdownText
85+
markdown={LINK_MARKDOWN}
86+
flavor="github"
87+
markdownStyle={style}
88+
onLinkPress={handleLinkPress}
89+
/>
90+
</RNGHPressable>
91+
</Section>
92+
93+
<Section
94+
title="RN PRESSABLE"
95+
subtitle="Control: link should fire onLinkPress normally"
96+
>
97+
<RNPressable
98+
onPress={() => handleParentPress('RNPressable')}
99+
style={styles.card}
100+
>
101+
<EnrichedMarkdownText
102+
markdown={LINK_MARKDOWN}
103+
flavor="github"
104+
markdownStyle={style}
105+
onLinkPress={handleLinkPress}
106+
/>
107+
</RNPressable>
108+
</Section>
109+
110+
<Section
111+
title="RNGH PRESSABLE (GITHUB FLAVOR)"
112+
subtitle="Same test with flavor='github' (GFM renderer)"
113+
>
114+
<RNGHPressable
115+
onPress={() => handleParentPress('RNGHPressable-github')}
116+
style={styles.card}
117+
>
118+
<EnrichedMarkdownText
119+
markdown={LINK_MARKDOWN}
120+
flavor="github"
121+
markdownStyle={style}
122+
onLinkPress={handleLinkPress}
123+
/>
124+
</RNGHPressable>
125+
</Section>
126+
127+
<Section
128+
title="NESTED RNGH PRESSABLE"
129+
subtitle="RNGH Pressable > View > EnrichedMarkdownText (deeper nesting)"
130+
>
131+
<RNGHPressable
132+
onPress={() => handleParentPress('RNGHPressable-nested')}
133+
style={styles.card}
134+
>
135+
<View style={styles.innerWrapper}>
136+
<Text style={styles.nestedLabel}>Nested wrapper:</Text>
137+
<EnrichedMarkdownText
138+
markdown={LINK_MARKDOWN}
139+
flavor="github"
140+
markdownStyle={style}
141+
onLinkPress={handleLinkPress}
142+
/>
143+
</View>
144+
</RNGHPressable>
145+
</Section>
146+
147+
<Section
148+
title="MULTIPLE RNGH PRESSABLES"
149+
subtitle="Two RNGH Pressables stacked (scroll-interference test)"
150+
>
151+
<RNGHPressable
152+
onPress={() => handleParentPress('RNGHPressable-multi-1')}
153+
style={styles.card}
154+
>
155+
<EnrichedMarkdownText
156+
markdown="First: tap [link one](https://one.example.com)"
157+
flavor="github"
158+
markdownStyle={style}
159+
onLinkPress={handleLinkPress}
160+
/>
161+
</RNGHPressable>
162+
<RNGHPressable
163+
onPress={() => handleParentPress('RNGHPressable-multi-2')}
164+
style={[styles.card, { marginTop: 8 }]}
165+
>
166+
<EnrichedMarkdownText
167+
markdown="Second: tap [link two](https://two.example.com)"
168+
flavor="github"
169+
markdownStyle={style}
170+
onLinkPress={handleLinkPress}
171+
/>
172+
</RNGHPressable>
173+
</Section>
174+
</ScrollView>
175+
);
176+
}
177+
178+
const styles = StyleSheet.create({
179+
scrollView: {
180+
flex: 1,
181+
backgroundColor: '#f5f5f5',
182+
},
183+
content: {
184+
padding: 16,
185+
paddingBottom: 48,
186+
},
187+
header: {
188+
fontSize: 14,
189+
color: '#666',
190+
marginBottom: 24,
191+
lineHeight: 20,
192+
},
193+
section: {
194+
marginBottom: 24,
195+
},
196+
sectionTitle: {
197+
fontSize: 13,
198+
fontWeight: '700',
199+
color: '#333',
200+
letterSpacing: 0.5,
201+
marginBottom: 2,
202+
},
203+
sectionSubtitle: {
204+
fontSize: 12,
205+
color: '#888',
206+
marginBottom: 8,
207+
},
208+
card: {
209+
backgroundColor: '#fff',
210+
borderRadius: 8,
211+
padding: 16,
212+
elevation: 1,
213+
shadowColor: '#000',
214+
shadowOffset: { width: 0, height: 1 },
215+
shadowOpacity: 0.1,
216+
shadowRadius: 2,
217+
},
218+
innerWrapper: {
219+
gap: 4,
220+
},
221+
nestedLabel: {
222+
fontSize: 12,
223+
color: '#999',
224+
},
225+
});

‎apps/react-native-example/src/screens/home/HomeScreen.tsx‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ const SCREENS: ScreenItem[] = [
5151
testID: 'home-block-storybook',
5252
color: '#FF2D55',
5353
},
54+
{
55+
route: 'GestureHandlerRepro',
56+
label: 'Gesture Handler Repro',
57+
subtext: 'RNGH Pressable + link press (#475)',
58+
testID: 'home-block-gesture-handler-repro',
59+
color: '#5856D6',
60+
},
5461
];
5562

5663
export default function HomeScreen({ navigation }: Props) {

0 commit comments

Comments
 (0)