0
# Interactive Components
1
2
User interaction components including buttons, touchables, and pressable elements with comprehensive gesture handling, accessibility support, and rich visual feedback capabilities.
3
4
## Button
5
6
A basic button component with built-in styling and accessibility features. Simple to use with minimal configuration required.
7
8
```javascript { .api }
9
const Button: React.ComponentType<ButtonProps>;
10
```
11
12
**Props:**
13
- `title` - Button text (required)
14
- `onPress` - Press event handler
15
- `disabled` - Whether button is disabled
16
- `color` - Button background color
17
- `accessibilityLabel` - Screen reader label
18
- `testID` - Test identifier
19
20
**Usage:**
21
```javascript
22
import { Button } from "react-native-web";
23
24
<Button
25
title="Click Me"
26
onPress={() => alert('Button pressed!')}
27
color="#2196F3"
28
disabled={false}
29
/>
30
31
// Custom styling via color
32
<Button
33
title="Success"
34
onPress={handleSubmit}
35
color="#4CAF50"
36
accessibilityLabel="Submit form"
37
/>
38
```
39
40
*Note: Button is deprecated in favor of Pressable for more advanced use cases.*
41
42
## Pressable
43
44
The most advanced and flexible interactive component with rich state management, hover support, and customizable styling based on interaction states.
45
46
```javascript { .api }
47
const Pressable: React.ComponentType<PressableProps>;
48
```
49
50
**Props:**
51
- `children` - Content or function that receives interaction state: `(state: {hovered, focused, pressed}) => React.Node`
52
- `onPress` - Press event handler
53
- `onPressIn` - Press start handler
54
- `onPressOut` - Press end handler
55
- `onLongPress` - Long press handler
56
- `onHoverIn` - Mouse hover start handler (web only)
57
- `onHoverOut` - Mouse hover end handler (web only)
58
- `disabled` - Whether component is disabled
59
- `delayLongPress` - Long press delay in milliseconds
60
- `delayPressIn` - Press in delay in milliseconds
61
- `delayPressOut` - Press out delay in milliseconds
62
- `style` - Style object or function that receives interaction state
63
64
**Interaction State:**
65
- `focused` - Component has keyboard focus
66
- `hovered` - Mouse is hovering (web only)
67
- `pressed` - Component is currently pressed
68
69
**Usage:**
70
```javascript
71
import { Pressable, Text } from "react-native-web";
72
73
// Basic pressable
74
<Pressable onPress={() => console.log('Pressed!')}>
75
<Text>Press me</Text>
76
</Pressable>
77
78
// Dynamic styling based on state
79
<Pressable
80
onPress={handlePress}
81
style={({pressed, hovered}) => ({
82
backgroundColor: pressed ? '#ddd' : hovered ? '#eee' : '#f5f5f5',
83
padding: 16,
84
borderRadius: 8,
85
transform: pressed ? 'scale(0.98)' : 'scale(1)',
86
})}
87
>
88
<Text>Interactive Button</Text>
89
</Pressable>
90
91
// Function children with state
92
<Pressable
93
onPress={handlePress}
94
onLongPress={handleLongPress}
95
delayLongPress={800}
96
>
97
{({pressed, hovered, focused}) => (
98
<View style={{
99
padding: 12,
100
backgroundColor: pressed ? '#007AFF' : '#f0f0f0',
101
borderRadius: 6,
102
borderWidth: focused ? 2 : 0,
103
borderColor: '#007AFF',
104
}}>
105
<Text style={{
106
color: pressed ? '#fff' : '#000',
107
fontWeight: hovered ? 'bold' : 'normal'
108
}}>
109
{pressed ? 'Pressed!' : 'Press & Hold'}
110
</Text>
111
</View>
112
)}
113
</Pressable>
114
115
// Complex interaction handling
116
<Pressable
117
onPress={() => navigation.navigate('Details')}
118
onHoverIn={() => setIsHovered(true)}
119
onHoverOut={() => setIsHovered(false)}
120
onPressIn={() => Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light)}
121
style={({pressed, hovered}) => [
122
styles.card,
123
pressed && styles.cardPressed,
124
hovered && styles.cardHovered
125
]}
126
>
127
<Text>Navigate to Details</Text>
128
</Pressable>
129
```
130
131
## TouchableOpacity
132
133
A wrapper that reduces opacity when pressed, providing visual feedback. Simpler than Pressable but with less flexibility.
134
135
```javascript { .api }
136
const TouchableOpacity: React.ComponentType<TouchableOpacityProps>;
137
```
138
139
**Props:**
140
- `activeOpacity` - Opacity when pressed (default: 0.2)
141
- `onPress` - Press event handler
142
- `onPressIn` - Press start handler
143
- `onPressOut` - Press end handler
144
- `onLongPress` - Long press handler
145
- `disabled` - Whether component is disabled
146
- `delayPressIn` - Press in delay in milliseconds
147
- `delayPressOut` - Press out delay in milliseconds
148
- `delayLongPress` - Long press delay in milliseconds
149
- `style` - Component styling
150
- `children` - Child components
151
152
**Usage:**
153
```javascript
154
import { TouchableOpacity, Text, View } from "react-native-web";
155
156
<TouchableOpacity
157
onPress={() => console.log('Pressed!')}
158
activeOpacity={0.6}
159
style={{
160
backgroundColor: '#007AFF',
161
padding: 16,
162
borderRadius: 8,
163
alignItems: 'center'
164
}}
165
>
166
<Text style={{ color: 'white', fontWeight: 'bold' }}>
167
Tap Me
168
</Text>
169
</TouchableOpacity>
170
171
// Custom opacity and timing
172
<TouchableOpacity
173
onPress={handlePress}
174
onLongPress={handleLongPress}
175
activeOpacity={0.8}
176
delayPressIn={100}
177
delayPressOut={200}
178
delayLongPress={1000}
179
>
180
<View style={styles.button}>
181
<Text>Custom Timing</Text>
182
</View>
183
</TouchableOpacity>
184
```
185
186
*Note: TouchableOpacity is deprecated in favor of Pressable.*
187
188
## TouchableHighlight
189
190
Shows an underlay color when pressed by reducing the child opacity and showing a background color.
191
192
```javascript { .api }
193
const TouchableHighlight: React.ComponentType<TouchableHighlightProps>;
194
```
195
196
**Props:**
197
- `underlayColor` - Background color when pressed (default: 'black')
198
- `activeOpacity` - Child opacity when pressed (default: 0.85)
199
- `onPress` - Press event handler
200
- `onPressIn` - Press start handler
201
- `onPressOut` - Press end handler
202
- `onLongPress` - Long press handler
203
- `onShowUnderlay` - Called when underlay is shown
204
- `onHideUnderlay` - Called when underlay is hidden
205
- `disabled` - Whether component is disabled
206
- `style` - Component styling
207
- `children` - Single child component (required)
208
209
**Usage:**
210
```javascript
211
import { TouchableHighlight, Text, View } from "react-native-web";
212
213
<TouchableHighlight
214
onPress={() => console.log('Pressed!')}
215
underlayColor="#DDDDDD"
216
activeOpacity={0.7}
217
style={{
218
backgroundColor: '#f0f0f0',
219
padding: 16,
220
borderRadius: 8
221
}}
222
>
223
<Text>Highlight on Press</Text>
224
</TouchableHighlight>
225
226
// Custom underlay behavior
227
<TouchableHighlight
228
onPress={handlePress}
229
underlayColor="rgba(0, 122, 255, 0.1)"
230
activeOpacity={0.9}
231
onShowUnderlay={() => console.log('Showing highlight')}
232
onHideUnderlay={() => console.log('Hiding highlight')}
233
>
234
<View style={styles.listItem}>
235
<Text>List Item with Highlight</Text>
236
</View>
237
</TouchableHighlight>
238
```
239
240
*Note: TouchableHighlight must have exactly one child component.*
241
242
## TouchableWithoutFeedback
243
244
Captures touch events without providing visual feedback. Useful for creating custom interactive areas.
245
246
```javascript { .api }
247
const TouchableWithoutFeedback: React.ComponentType<TouchableWithoutFeedbackProps>;
248
```
249
250
**Props:**
251
- `onPress` - Press event handler
252
- `onPressIn` - Press start handler
253
- `onPressOut` - Press end handler
254
- `onLongPress` - Long press handler
255
- `disabled` - Whether component is disabled
256
- `delayPressIn` - Press in delay in milliseconds
257
- `delayPressOut` - Press out delay in milliseconds
258
- `delayLongPress` - Long press delay in milliseconds
259
- `accessibilityLabel` - Screen reader label
260
- `accessibilityRole` - Semantic role
261
- `children` - Single child component (required)
262
263
**Usage:**
264
```javascript
265
import { TouchableWithoutFeedback, View, Text } from "react-native-web";
266
267
<TouchableWithoutFeedback
268
onPress={() => console.log('Area pressed')}
269
onLongPress={() => showContextMenu()}
270
>
271
<View style={{ padding: 20, backgroundColor: '#f5f5f5' }}>
272
<Text>Pressable area with no visual feedback</Text>
273
</View>
274
</TouchableWithoutFeedback>
275
276
// Custom gesture handling
277
<TouchableWithoutFeedback
278
onPressIn={() => setPressed(true)}
279
onPressOut={() => setPressed(false)}
280
onLongPress={handleLongPress}
281
delayLongPress={500}
282
>
283
<View style={[
284
styles.customArea,
285
pressed && styles.customAreaPressed
286
]}>
287
<Text>Custom Feedback Area</Text>
288
</View>
289
</TouchableWithoutFeedback>
290
```
291
292
*Note: TouchableWithoutFeedback must have exactly one child component.*
293
294
## TouchableNativeFeedback
295
296
Provides Material Design ripple effect on Android. On web, falls back to TouchableWithoutFeedback behavior.
297
298
```javascript { .api }
299
const TouchableNativeFeedback: React.ComponentType<TouchableNativeFeedbackProps>;
300
```
301
302
**Props:**
303
- `background` - Ripple background configuration (Android only)
304
- `useForeground` - Whether to use foreground ripple (Android only)
305
- `onPress` - Press event handler
306
- `disabled` - Whether component is disabled
307
- `children` - Single child component (required)
308
309
**Usage:**
310
```javascript
311
import { TouchableNativeFeedback, View, Text } from "react-native-web";
312
313
<TouchableNativeFeedback
314
onPress={() => console.log('Pressed!')}
315
background={TouchableNativeFeedback.Ripple('#000', false)}
316
>
317
<View style={styles.button}>
318
<Text>Material Design Button</Text>
319
</View>
320
</TouchableNativeFeedback>
321
322
// Borderless ripple
323
<TouchableNativeFeedback
324
onPress={handlePress}
325
background={TouchableNativeFeedback.Ripple('#007AFF', true)}
326
useForeground={true}
327
>
328
<View style={styles.iconButton}>
329
<Icon name="heart" />
330
</View>
331
</TouchableNativeFeedback>
332
```
333
334
*Note: On web, this component provides basic touch handling without the native ripple effect.*
335
336
## Types
337
338
```javascript { .api }
339
interface ButtonProps {
340
title: string;
341
onPress?: (event: PressEvent) => void;
342
disabled?: boolean;
343
color?: string;
344
accessibilityLabel?: string;
345
testID?: string;
346
}
347
348
interface StateCallbackType {
349
focused: boolean;
350
hovered: boolean;
351
pressed: boolean;
352
}
353
354
interface PressableProps extends ViewProps {
355
children: React.ReactNode | ((state: StateCallbackType) => React.ReactNode);
356
onPress?: (event: PressEvent) => void;
357
onPressIn?: (event: PressEvent) => void;
358
onPressOut?: (event: PressEvent) => void;
359
onLongPress?: (event: PressEvent) => void;
360
onHoverIn?: (event: HoverEvent) => void;
361
onHoverOut?: (event: HoverEvent) => void;
362
disabled?: boolean;
363
delayLongPress?: number;
364
delayPressIn?: number;
365
delayPressOut?: number;
366
style?: ViewStyle | ((state: StateCallbackType) => ViewStyle);
367
}
368
369
interface TouchableOpacityProps extends ViewProps {
370
activeOpacity?: number;
371
onPress?: (event: PressEvent) => void;
372
onPressIn?: (event: PressEvent) => void;
373
onPressOut?: (event: PressEvent) => void;
374
onLongPress?: (event: PressEvent) => void;
375
disabled?: boolean;
376
delayPressIn?: number;
377
delayPressOut?: number;
378
delayLongPress?: number;
379
style?: ViewStyle;
380
children?: React.ReactNode;
381
}
382
383
interface TouchableHighlightProps extends ViewProps {
384
underlayColor?: ColorValue;
385
activeOpacity?: number;
386
onPress?: (event: PressEvent) => void;
387
onPressIn?: (event: PressEvent) => void;
388
onPressOut?: (event: PressEvent) => void;
389
onLongPress?: (event: PressEvent) => void;
390
onShowUnderlay?: () => void;
391
onHideUnderlay?: () => void;
392
disabled?: boolean;
393
style?: ViewStyle;
394
children: React.ReactElement; // Must have exactly one child
395
}
396
397
interface TouchableWithoutFeedbackProps {
398
onPress?: (event: PressEvent) => void;
399
onPressIn?: (event: PressEvent) => void;
400
onPressOut?: (event: PressEvent) => void;
401
onLongPress?: (event: PressEvent) => void;
402
disabled?: boolean;
403
delayPressIn?: number;
404
delayPressOut?: number;
405
delayLongPress?: number;
406
accessibilityLabel?: string;
407
accessibilityRole?: string;
408
children: React.ReactElement; // Must have exactly one child
409
}
410
411
interface TouchableNativeFeedbackProps {
412
onPress?: (event: PressEvent) => void;
413
disabled?: boolean;
414
background?: any; // Platform-specific ripple configuration
415
useForeground?: boolean;
416
children: React.ReactElement; // Must have exactly one child
417
}
418
```