0
# Form Controls
1
2
Form input components including switches, checkboxes, pickers, progress indicators, and activity indicators with comprehensive styling, accessibility, and user interaction support.
3
4
## Switch
5
6
A toggle switch component that provides binary on/off functionality with smooth animations and customizable colors.
7
8
```javascript { .api }
9
const Switch: React.ComponentType<SwitchProps>;
10
```
11
12
**Props:**
13
- `value` - Whether the switch is on (default: false)
14
- `onValueChange` - Callback when switch state changes: `(value: boolean) => void`
15
- `disabled` - Whether switch is disabled
16
- `thumbColor` - Color of the thumb when off
17
- `activeThumbColor` - Color of the thumb when on
18
- `trackColor` - Track color (string or object with true/false states)
19
- `activeTrackColor` - Track color when on (deprecated, use trackColor)
20
- `accessibilityLabel` - Screen reader label
21
- `style` - Component styling
22
23
**Track Color Options:**
24
```javascript
25
// Simple color
26
trackColor="#ccc"
27
28
// Different colors for on/off states
29
trackColor={{
30
false: '#767577', // Color when switch is off
31
true: '#81b0ff' // Color when switch is on
32
}}
33
```
34
35
**Usage:**
36
```javascript
37
import { Switch, View, Text } from "react-native-web";
38
39
function Settings() {
40
const [isEnabled, setIsEnabled] = useState(false);
41
const [notifications, setNotifications] = useState(true);
42
43
return (
44
<View style={{ padding: 20 }}>
45
{/* Basic switch */}
46
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
47
<Text style={{ flex: 1 }}>Enable feature</Text>
48
<Switch
49
value={isEnabled}
50
onValueChange={setIsEnabled}
51
/>
52
</View>
53
54
{/* Custom colors */}
55
<View style={{ flexDirection: 'row', alignItems: 'center', marginBottom: 20 }}>
56
<Text style={{ flex: 1 }}>Push notifications</Text>
57
<Switch
58
value={notifications}
59
onValueChange={setNotifications}
60
thumbColor={notifications ? '#4CAF50' : '#f4f3f4'}
61
trackColor={{ false: '#767577', true: '#81b0ff' }}
62
/>
63
</View>
64
65
{/* Disabled switch */}
66
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
67
<Text style={{ flex: 1, color: '#999' }}>Premium feature</Text>
68
<Switch
69
value={false}
70
disabled={true}
71
thumbColor="#ccc"
72
trackColor="#ddd"
73
/>
74
</View>
75
</View>
76
);
77
}
78
79
// Custom sized switch
80
<Switch
81
value={isOn}
82
onValueChange={setIsOn}
83
style={{ height: 30, width: 60 }}
84
thumbColor="#fff"
85
activeThumbColor="#007AFF"
86
trackColor={{ false: '#ccc', true: '#007AFF' }}
87
/>
88
```
89
90
## CheckBox
91
92
A checkbox component for multiple selection with customizable styling and accessibility support.
93
94
```javascript { .api }
95
const CheckBox: React.ComponentType<CheckBoxProps>;
96
```
97
98
**Props:**
99
- `value` - Whether checkbox is checked
100
- `onValueChange` - Callback when checkbox state changes: `(value: boolean) => void`
101
- `onChange` - Raw change event handler
102
- `disabled` - Whether checkbox is disabled
103
- `readOnly` - Whether checkbox is read-only
104
- `color` - Checkbox color when checked
105
- `accessibilityLabel` - Screen reader label
106
- `style` - Component styling
107
108
**Usage:**
109
```javascript
110
import { CheckBox, View, Text } from "react-native-web";
111
112
function TodoList() {
113
const [tasks, setTasks] = useState([
114
{ id: 1, text: 'Learn React Native Web', completed: false },
115
{ id: 2, text: 'Build an app', completed: true },
116
{ id: 3, text: 'Deploy to production', completed: false }
117
]);
118
119
const toggleTask = (id) => {
120
setTasks(tasks.map(task =>
121
task.id === id ? { ...task, completed: !task.completed } : task
122
));
123
};
124
125
return (
126
<View style={{ padding: 20 }}>
127
{tasks.map(task => (
128
<View key={task.id} style={{
129
flexDirection: 'row',
130
alignItems: 'center',
131
marginBottom: 10
132
}}>
133
<CheckBox
134
value={task.completed}
135
onValueChange={() => toggleTask(task.id)}
136
color="#007AFF"
137
/>
138
<Text style={{
139
marginLeft: 10,
140
textDecorationLine: task.completed ? 'line-through' : 'none',
141
color: task.completed ? '#999' : '#000'
142
}}>
143
{task.text}
144
</Text>
145
</View>
146
))}
147
148
{/* Disabled checkbox */}
149
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 20 }}>
150
<CheckBox
151
value={true}
152
disabled={true}
153
color="#ccc"
154
/>
155
<Text style={{ marginLeft: 10, color: '#999' }}>
156
Read-only completed task
157
</Text>
158
</View>
159
160
{/* Custom styled checkbox */}
161
<View style={{ flexDirection: 'row', alignItems: 'center', marginTop: 10 }}>
162
<CheckBox
163
value={false}
164
onValueChange={() => {}}
165
color="#4CAF50"
166
style={{
167
transform: 'scale(1.2)',
168
margin: 2
169
}}
170
/>
171
<Text style={{ marginLeft: 15 }}>Large checkbox</Text>
172
</View>
173
</View>
174
);
175
}
176
```
177
178
## Picker
179
180
A dropdown picker component for selecting from a list of options, rendering as a native select element.
181
182
```javascript { .api }
183
const Picker: React.ComponentType<PickerProps>;
184
const Picker.Item: React.ComponentType<PickerItemProps>;
185
```
186
187
**Picker Props:**
188
- `selectedValue` - Currently selected value
189
- `onValueChange` - Selection change callback: `(value: string | number, index: number) => void`
190
- `enabled` - Whether picker is enabled (default: true)
191
- `children` - Picker.Item components
192
- `style` - Picker styling
193
- `testID` - Test identifier
194
195
**Picker.Item Props:**
196
- `label` - Display text for the option
197
- `value` - Value when this item is selected
198
- `color` - Text color for this item
199
- `testID` - Test identifier
200
201
**Usage:**
202
```javascript
203
import { Picker, View, Text } from "react-native-web";
204
205
function UserForm() {
206
const [selectedCountry, setSelectedCountry] = useState('usa');
207
const [selectedLanguage, setSelectedLanguage] = useState('en');
208
209
const countries = [
210
{ label: 'United States', value: 'usa' },
211
{ label: 'Canada', value: 'canada' },
212
{ label: 'United Kingdom', value: 'uk' },
213
{ label: 'Australia', value: 'australia' }
214
];
215
216
const languages = [
217
{ label: 'English', value: 'en' },
218
{ label: 'Spanish', value: 'es' },
219
{ label: 'French', value: 'fr' },
220
{ label: 'German', value: 'de' }
221
];
222
223
return (
224
<View style={{ padding: 20 }}>
225
{/* Basic picker */}
226
<View style={{ marginBottom: 20 }}>
227
<Text style={{ marginBottom: 5, fontSize: 16 }}>Country</Text>
228
<Picker
229
selectedValue={selectedCountry}
230
onValueChange={(value, index) => {
231
setSelectedCountry(value);
232
console.log(`Selected: ${countries[index].label}`);
233
}}
234
style={{
235
height: 50,
236
borderWidth: 1,
237
borderColor: '#ccc',
238
borderRadius: 5,
239
paddingHorizontal: 10
240
}}
241
>
242
{countries.map(country => (
243
<Picker.Item
244
key={country.value}
245
label={country.label}
246
value={country.value}
247
/>
248
))}
249
</Picker>
250
</View>
251
252
{/* Picker with custom item colors */}
253
<View style={{ marginBottom: 20 }}>
254
<Text style={{ marginBottom: 5, fontSize: 16 }}>Language</Text>
255
<Picker
256
selectedValue={selectedLanguage}
257
onValueChange={setSelectedLanguage}
258
style={{
259
height: 50,
260
borderWidth: 1,
261
borderColor: '#007AFF',
262
borderRadius: 5,
263
backgroundColor: '#f8f9fa'
264
}}
265
>
266
<Picker.Item label="Select a language..." value="" color="#999" />
267
{languages.map(lang => (
268
<Picker.Item
269
key={lang.value}
270
label={lang.label}
271
value={lang.value}
272
color="#333"
273
/>
274
))}
275
</Picker>
276
</View>
277
278
{/* Disabled picker */}
279
<View>
280
<Text style={{ marginBottom: 5, fontSize: 16, color: '#999' }}>
281
Premium Options
282
</Text>
283
<Picker
284
selectedValue="locked"
285
enabled={false}
286
style={{
287
height: 50,
288
borderWidth: 1,
289
borderColor: '#ddd',
290
borderRadius: 5,
291
backgroundColor: '#f5f5f5'
292
}}
293
>
294
<Picker.Item label="Upgrade to access" value="locked" color="#999" />
295
</Picker>
296
</View>
297
</View>
298
);
299
}
300
```
301
302
## ActivityIndicator
303
304
A spinning activity indicator for showing loading states with customizable size and color.
305
306
```javascript { .api }
307
const ActivityIndicator: React.ComponentType<ActivityIndicatorProps>;
308
```
309
310
**Props:**
311
- `animating` - Whether indicator is animating (default: true)
312
- `color` - Indicator color (default: '#1976D2')
313
- `size` - Size preset ('small' | 'large') or custom number
314
- `hidesWhenStopped` - Hide when not animating (default: true)
315
- `style` - Component styling
316
317
**Size Options:**
318
- `'small'` - 20x20 pixels
319
- `'large'` - 36x36 pixels
320
- `number` - Custom size in pixels
321
322
**Usage:**
323
```javascript
324
import { ActivityIndicator, View, Text, Button } from "react-native-web";
325
326
function LoadingExample() {
327
const [loading, setLoading] = useState(false);
328
const [data, setData] = useState(null);
329
330
const fetchData = async () => {
331
setLoading(true);
332
try {
333
// Simulate API call
334
await new Promise(resolve => setTimeout(resolve, 2000));
335
setData('Data loaded successfully!');
336
} finally {
337
setLoading(false);
338
}
339
};
340
341
return (
342
<View style={{ padding: 20, alignItems: 'center' }}>
343
{/* Basic loading indicator */}
344
<ActivityIndicator animating={loading} size="large" />
345
346
{/* Loading with text */}
347
{loading && (
348
<View style={{ alignItems: 'center', marginVertical: 20 }}>
349
<ActivityIndicator size="small" color="#007AFF" />
350
<Text style={{ marginTop: 10, color: '#666' }}>Loading...</Text>
351
</View>
352
)}
353
354
{/* Custom sized indicator */}
355
<ActivityIndicator
356
animating={true}
357
size={50}
358
color="#4CAF50"
359
style={{ margin: 20 }}
360
/>
361
362
{/* Inline with content */}
363
<View style={{
364
flexDirection: 'row',
365
alignItems: 'center',
366
marginVertical: 20
367
}}>
368
<Text>Processing</Text>
369
<ActivityIndicator
370
size="small"
371
color="#FF9800"
372
style={{ marginLeft: 10 }}
373
/>
374
</View>
375
376
<Button title="Fetch Data" onPress={fetchData} />
377
378
{data && (
379
<Text style={{ marginTop: 20, fontSize: 16, color: '#4CAF50' }}>
380
{data}
381
</Text>
382
)}
383
</View>
384
);
385
}
386
387
// Loading overlay
388
function LoadingOverlay({ visible }) {
389
if (!visible) return null;
390
391
return (
392
<View style={{
393
position: 'absolute',
394
top: 0,
395
left: 0,
396
right: 0,
397
bottom: 0,
398
backgroundColor: 'rgba(0,0,0,0.5)',
399
justifyContent: 'center',
400
alignItems: 'center',
401
zIndex: 1000
402
}}>
403
<View style={{
404
backgroundColor: 'white',
405
padding: 20,
406
borderRadius: 10,
407
alignItems: 'center'
408
}}>
409
<ActivityIndicator size="large" color="#007AFF" />
410
<Text style={{ marginTop: 10, fontSize: 16 }}>Please wait...</Text>
411
</View>
412
</View>
413
);
414
}
415
```
416
417
## ProgressBar
418
419
A progress bar component for showing completion status with determinate and indeterminate modes.
420
421
```javascript { .api }
422
const ProgressBar: React.ComponentType<ProgressBarProps>;
423
```
424
425
**Props:**
426
- `progress` - Progress value between 0 and 1 (default: 0)
427
- `indeterminate` - Show indeterminate animation (default: false)
428
- `color` - Progress bar color (default: '#1976D2')
429
- `trackColor` - Background track color (default: 'transparent')
430
- `style` - Component styling
431
432
**Usage:**
433
```javascript
434
import { ProgressBar, View, Text, Button } from "react-native-web";
435
436
function ProgressExample() {
437
const [progress, setProgress] = useState(0);
438
const [uploading, setUploading] = useState(false);
439
440
const simulateProgress = () => {
441
setProgress(0);
442
setUploading(true);
443
444
const timer = setInterval(() => {
445
setProgress(prev => {
446
const next = prev + 0.1;
447
if (next >= 1) {
448
clearInterval(timer);
449
setUploading(false);
450
return 1;
451
}
452
return next;
453
});
454
}, 200);
455
};
456
457
return (
458
<View style={{ padding: 20 }}>
459
{/* Basic progress bar */}
460
<View style={{ marginBottom: 20 }}>
461
<Text style={{ marginBottom: 10 }}>Download Progress</Text>
462
<ProgressBar
463
progress={0.7}
464
color="#4CAF50"
465
trackColor="#e0e0e0"
466
style={{ height: 8, borderRadius: 4 }}
467
/>
468
<Text style={{ marginTop: 5, fontSize: 12, color: '#666' }}>
469
70% Complete
470
</Text>
471
</View>
472
473
{/* Dynamic progress */}
474
<View style={{ marginBottom: 20 }}>
475
<Text style={{ marginBottom: 10 }}>Upload Progress</Text>
476
<ProgressBar
477
progress={progress}
478
color="#007AFF"
479
trackColor="#f0f0f0"
480
style={{ height: 6, borderRadius: 3 }}
481
/>
482
<Text style={{ marginTop: 5, fontSize: 12, color: '#666' }}>
483
{Math.round(progress * 100)}% Complete
484
</Text>
485
<Button
486
title={uploading ? "Uploading..." : "Start Upload"}
487
onPress={simulateProgress}
488
disabled={uploading}
489
/>
490
</View>
491
492
{/* Indeterminate progress */}
493
<View style={{ marginBottom: 20 }}>
494
<Text style={{ marginBottom: 10 }}>Processing...</Text>
495
<ProgressBar
496
indeterminate={true}
497
color="#FF9800"
498
trackColor="#fff3e0"
499
style={{ height: 4, borderRadius: 2 }}
500
/>
501
</View>
502
503
{/* Custom styled progress bars */}
504
<View style={{ marginBottom: 10 }}>
505
<Text style={{ marginBottom: 10 }}>Custom Styles</Text>
506
507
{/* Thick progress bar */}
508
<ProgressBar
509
progress={0.3}
510
color="#E91E63"
511
trackColor="#fce4ec"
512
style={{ height: 12, borderRadius: 6, marginBottom: 10 }}
513
/>
514
515
{/* Thin progress bar */}
516
<ProgressBar
517
progress={0.8}
518
color="#9C27B0"
519
trackColor="#f3e5f5"
520
style={{ height: 2, borderRadius: 1 }}
521
/>
522
</View>
523
</View>
524
);
525
}
526
527
// Progress with multiple steps
528
function StepProgress({ currentStep, totalSteps }) {
529
const progress = currentStep / totalSteps;
530
531
return (
532
<View style={{ padding: 20 }}>
533
<Text style={{ marginBottom: 10, fontSize: 16 }}>
534
Step {currentStep} of {totalSteps}
535
</Text>
536
<ProgressBar
537
progress={progress}
538
color="#007AFF"
539
trackColor="#e5e5ea"
540
style={{
541
height: 8,
542
borderRadius: 4,
543
backgroundColor: '#e5e5ea'
544
}}
545
/>
546
</View>
547
);
548
}
549
```
550
551
## Types
552
553
```javascript { .api }
554
interface SwitchProps extends ViewProps {
555
value?: boolean;
556
onValueChange?: (value: boolean) => void;
557
disabled?: boolean;
558
thumbColor?: ColorValue;
559
activeThumbColor?: ColorValue;
560
trackColor?: ColorValue | { false: ColorValue; true: ColorValue };
561
activeTrackColor?: ColorValue; // deprecated
562
accessibilityLabel?: string;
563
style?: ViewStyle;
564
}
565
566
interface CheckBoxProps extends ViewProps {
567
value?: boolean;
568
onValueChange?: (value: boolean) => void;
569
onChange?: (event: ChangeEvent) => void;
570
disabled?: boolean;
571
readOnly?: boolean;
572
color?: ColorValue;
573
accessibilityLabel?: string;
574
style?: ViewStyle;
575
}
576
577
interface PickerProps extends ViewProps {
578
selectedValue?: string | number;
579
onValueChange?: (value: string | number, index: number) => void;
580
enabled?: boolean;
581
children?: React.ReactNode;
582
style?: ViewStyle;
583
testID?: string;
584
}
585
586
interface PickerItemProps {
587
label: string;
588
value?: string | number;
589
color?: ColorValue;
590
testID?: string;
591
}
592
593
interface ActivityIndicatorProps extends ViewProps {
594
animating?: boolean;
595
color?: string;
596
size?: 'small' | 'large' | number;
597
hidesWhenStopped?: boolean;
598
style?: ViewStyle;
599
}
600
601
interface ProgressBarProps extends ViewProps {
602
progress?: number; // 0 to 1
603
indeterminate?: boolean;
604
color?: ColorValue;
605
trackColor?: ColorValue;
606
style?: ViewStyle;
607
}
608
```