0
# Theming System
1
2
Comprehensive theming engine with context providers, hooks, and HOCs for consistent design across your React Native Elements application with support for dark mode, custom colors, and component-specific overrides.
3
4
## Capabilities
5
6
### ThemeProvider
7
8
Context provider component for theme management that wraps your application to provide theme context to all React Native Elements components.
9
10
```typescript { .api }
11
/**
12
* Context provider for theme management
13
*/
14
interface ThemeProviderProps {
15
/** Theme configuration */
16
theme: Partial<FullTheme>;
17
/** Enable dark mode */
18
useDark?: boolean;
19
/** Children components */
20
children: React.ReactNode;
21
}
22
23
/**
24
* Complete theme configuration interface
25
*/
26
interface FullTheme {
27
/** Color palette */
28
colors: Colors;
29
/** Component-specific theme overrides */
30
Button: Partial<ButtonProps>;
31
Input: Partial<InputProps>;
32
Header: Partial<HeaderProps>;
33
Card: Partial<CardProps>;
34
ListItem: Partial<ListItemProps>;
35
Text: Partial<TextProps>;
36
Icon: Partial<IconProps>;
37
CheckBox: Partial<CheckBoxProps>;
38
Avatar: Partial<AvatarProps>;
39
Badge: Partial<BadgeProps>;
40
Divider: Partial<DividerProps>;
41
SearchBar: Partial<SearchBarProps>;
42
Slider: Partial<SliderProps>;
43
ButtonGroup: Partial<ButtonGroupProps>;
44
Overlay: Partial<OverlayProps>;
45
Tooltip: Partial<TooltipProps>;
46
BottomSheet: Partial<BottomSheetProps>;
47
PricingCard: Partial<PricingCardProps>;
48
Tile: Partial<TileProps>;
49
Image: Partial<ImageProps>;
50
}
51
52
/**
53
* Color palette interface
54
*/
55
interface Colors {
56
/** Primary brand color */
57
primary: string;
58
/** Secondary brand color */
59
secondary: string;
60
/** Success state color */
61
success: string;
62
/** Warning state color */
63
warning: string;
64
/** Error state color */
65
error: string;
66
/** White color */
67
white: string;
68
/** Black color */
69
black: string;
70
/** Grey scale colors (darkest to lightest) */
71
grey0: string;
72
grey1: string;
73
grey2: string;
74
grey3: string;
75
grey4: string;
76
grey5: string;
77
/** Border/outline grey */
78
greyOutline: string;
79
/** Search background color */
80
searchBg: string;
81
/** Disabled element color */
82
disabled: string;
83
/** Divider line color */
84
divider: string;
85
/** Platform-specific color overrides */
86
platform: {
87
ios: Partial<Colors>;
88
android: Partial<Colors>;
89
web: Partial<Colors>;
90
};
91
}
92
```
93
94
**Usage Examples:**
95
96
```typescript
97
import React from 'react';
98
import { ThemeProvider } from 'react-native-elements';
99
100
// Basic theme setup
101
const theme = {
102
colors: {
103
primary: '#007AFF',
104
secondary: '#5856D6',
105
success: '#34C759',
106
warning: '#FF9500',
107
error: '#FF3B30',
108
}
109
};
110
111
function App() {
112
return (
113
<ThemeProvider theme={theme}>
114
<MyAppContent />
115
</ThemeProvider>
116
);
117
}
118
119
// Dark mode theme
120
const darkTheme = {
121
colors: {
122
primary: '#0A84FF',
123
secondary: '#5E5CE6',
124
white: '#000000',
125
black: '#FFFFFF',
126
grey0: '#FFFFFF',
127
grey1: '#F2F2F7',
128
grey2: '#E5E5EA',
129
grey3: '#D1D1D6',
130
grey4: '#C7C7CC',
131
grey5: '#AEAEB2',
132
searchBg: '#1C1C1E',
133
divider: '#38383A',
134
}
135
};
136
137
// Component-specific theme overrides
138
const customTheme = {
139
colors: {
140
primary: '#6366F1',
141
secondary: '#8B5CF6',
142
},
143
Button: {
144
buttonStyle: {
145
borderRadius: 25,
146
paddingHorizontal: 30,
147
},
148
titleStyle: {
149
fontWeight: 'bold',
150
},
151
},
152
Input: {
153
inputContainerStyle: {
154
borderBottomWidth: 2,
155
borderRadius: 5,
156
paddingHorizontal: 10,
157
},
158
},
159
Header: {
160
backgroundColor: '#6366F1',
161
centerComponent: {
162
style: {
163
color: '#fff',
164
fontSize: 20,
165
fontWeight: 'bold'
166
}
167
},
168
},
169
};
170
171
<ThemeProvider theme={customTheme}>
172
<App />
173
</ThemeProvider>
174
175
// Platform-specific theming
176
const platformTheme = {
177
colors: {
178
primary: '#007AFF',
179
platform: {
180
ios: {
181
primary: '#007AFF',
182
searchBg: '#E5E5EA',
183
},
184
android: {
185
primary: '#2196F3',
186
searchBg: '#F5F5F5',
187
},
188
web: {
189
primary: '#0066CC',
190
searchBg: '#FAFAFA',
191
},
192
},
193
},
194
};
195
```
196
197
### useTheme Hook
198
199
React hook for accessing theme context in functional components, providing theme values and update functions.
200
201
```typescript { .api }
202
/**
203
* React hook for accessing theme context
204
* @returns Theme context object with theme values and update functions
205
*/
206
function useTheme(): ThemeContextValue;
207
208
/**
209
* Theme context value interface
210
*/
211
interface ThemeContextValue {
212
/** Current theme configuration */
213
theme: FullTheme;
214
/** Update theme partially */
215
updateTheme: UpdateTheme;
216
/** Replace entire theme */
217
replaceTheme: ReplaceTheme;
218
}
219
220
/**
221
* Function type for updating theme partially
222
*/
223
type UpdateTheme = (updates: Partial<FullTheme>) => void;
224
225
/**
226
* Function type for replacing entire theme
227
*/
228
type ReplaceTheme = (theme: FullTheme) => void;
229
```
230
231
**Usage Examples:**
232
233
```typescript
234
import React from 'react';
235
import { useTheme } from 'react-native-elements';
236
import { View, Text, Button } from 'react-native';
237
238
// Basic theme usage
239
function MyComponent() {
240
const { theme } = useTheme();
241
242
return (
243
<View style={{ backgroundColor: theme.colors.primary, padding: 20 }}>
244
<Text style={{ color: theme.colors.white }}>
245
Themed Component
246
</Text>
247
</View>
248
);
249
}
250
251
// Theme updates
252
function ThemeControls() {
253
const { theme, updateTheme, replaceTheme } = useTheme();
254
255
const switchToDarkMode = () => {
256
updateTheme({
257
colors: {
258
...theme.colors,
259
white: '#000000',
260
black: '#FFFFFF',
261
grey0: '#FFFFFF',
262
grey5: '#1C1C1E',
263
}
264
});
265
};
266
267
const resetTheme = () => {
268
replaceTheme({
269
colors: {
270
primary: '#007AFF',
271
secondary: '#5856D6',
272
// ... full theme object
273
},
274
// ... other theme properties
275
});
276
};
277
278
return (
279
<View>
280
<Button title="Dark Mode" onPress={switchToDarkMode} />
281
<Button title="Reset Theme" onPress={resetTheme} />
282
</View>
283
);
284
}
285
286
// Dynamic styling with theme
287
function DynamicComponent() {
288
const { theme } = useTheme();
289
290
const dynamicStyles = {
291
container: {
292
backgroundColor: theme.colors.white,
293
borderColor: theme.colors.greyOutline,
294
borderWidth: 1,
295
},
296
text: {
297
color: theme.colors.black,
298
fontSize: 16,
299
},
300
button: {
301
backgroundColor: theme.colors.primary,
302
borderRadius: 8,
303
},
304
};
305
306
return (
307
<View style={dynamicStyles.container}>
308
<Text style={dynamicStyles.text}>Dynamic Theme Content</Text>
309
<TouchableOpacity style={dynamicStyles.button}>
310
<Text style={{ color: theme.colors.white }}>Action</Text>
311
</TouchableOpacity>
312
</View>
313
);
314
}
315
```
316
317
### makeStyles Hook
318
319
Creates dynamic styles based on theme and props, providing a powerful way to create responsive and theme-aware stylesheets.
320
321
```typescript { .api }
322
/**
323
* Creates dynamic styles based on theme and props
324
* @param styles - Style object or function that returns style object
325
* @returns Hook function that returns computed styles
326
*/
327
function makeStyles<T extends StyleSheet.NamedStyles<T> | StyleSheet.NamedStyles<any>>(
328
styles: T | ((theme: FullTheme, props?: any) => T)
329
): (props?: any) => T;
330
```
331
332
**Usage Examples:**
333
334
```typescript
335
import React from 'react';
336
import { makeStyles } from 'react-native-elements';
337
import { View, Text } from 'react-native';
338
339
// Basic makeStyles usage
340
const useStyles = makeStyles((theme) => ({
341
container: {
342
backgroundColor: theme.colors.white,
343
padding: 20,
344
borderRadius: 10,
345
shadowColor: theme.colors.black,
346
shadowOffset: { width: 0, height: 2 },
347
shadowOpacity: 0.1,
348
shadowRadius: 4,
349
},
350
title: {
351
color: theme.colors.black,
352
fontSize: 18,
353
fontWeight: 'bold',
354
marginBottom: 10,
355
},
356
primaryButton: {
357
backgroundColor: theme.colors.primary,
358
borderRadius: 8,
359
paddingVertical: 12,
360
paddingHorizontal: 24,
361
},
362
}));
363
364
function StyledComponent() {
365
const styles = useStyles();
366
367
return (
368
<View style={styles.container}>
369
<Text style={styles.title}>Styled Component</Text>
370
<TouchableOpacity style={styles.primaryButton}>
371
<Text style={{ color: 'white' }}>Action</Text>
372
</TouchableOpacity>
373
</View>
374
);
375
}
376
377
// makeStyles with props
378
const useCardStyles = makeStyles((theme, props) => ({
379
card: {
380
backgroundColor: props.highlighted ? theme.colors.primary : theme.colors.white,
381
borderColor: props.highlighted ? theme.colors.primary : theme.colors.greyOutline,
382
borderWidth: props.highlighted ? 2 : 1,
383
borderRadius: props.rounded ? 15 : 5,
384
padding: 20,
385
margin: 10,
386
},
387
text: {
388
color: props.highlighted ? theme.colors.white : theme.colors.black,
389
fontSize: props.large ? 18 : 14,
390
fontWeight: props.bold ? 'bold' : 'normal',
391
},
392
}));
393
394
function Card({ title, highlighted, rounded, large, bold }) {
395
const styles = useCardStyles({ highlighted, rounded, large, bold });
396
397
return (
398
<View style={styles.card}>
399
<Text style={styles.text}>{title}</Text>
400
</View>
401
);
402
}
403
404
// Responsive styles with makeStyles
405
const useResponsiveStyles = makeStyles((theme) => ({
406
container: {
407
flex: 1,
408
backgroundColor: theme.colors.white,
409
},
410
grid: {
411
flexDirection: 'row',
412
flexWrap: 'wrap',
413
justifyContent: 'space-between',
414
},
415
gridItem: {
416
width: '48%',
417
backgroundColor: theme.colors.grey5,
418
borderRadius: 8,
419
padding: 15,
420
marginBottom: 15,
421
},
422
// Platform-specific styles
423
...(Platform.OS === 'ios' && {
424
iosSpecific: {
425
shadowColor: theme.colors.black,
426
shadowOffset: { width: 0, height: 2 },
427
shadowOpacity: 0.1,
428
shadowRadius: 4,
429
},
430
}),
431
...(Platform.OS === 'android' && {
432
androidSpecific: {
433
elevation: 4,
434
},
435
}),
436
}));
437
```
438
439
### withTheme HOC
440
441
Higher-Order Component that injects theme props into components, useful for class components or when you need theme props injected directly.
442
443
```typescript { .api }
444
/**
445
* Higher-Order Component that injects theme props into components
446
* @param Component - Component to wrap with theme
447
* @param themeKey - Optional theme key for component-specific overrides
448
* @returns Enhanced component with theme props
449
*/
450
function withTheme<P, T = {}>(
451
Component: React.ComponentType<P & ThemeProps<T>>,
452
themeKey?: keyof FullTheme
453
): React.ComponentType<P>;
454
455
/**
456
* Props injected by withTheme HOC
457
*/
458
interface ThemeProps<T = {}> {
459
/** Current theme configuration */
460
theme: FullTheme;
461
/** Update theme partially */
462
updateTheme: UpdateTheme;
463
/** Replace entire theme */
464
replaceTheme: ReplaceTheme;
465
}
466
```
467
468
**Usage Examples:**
469
470
```typescript
471
import React from 'react';
472
import { withTheme } from 'react-native-elements';
473
import { View, Text } from 'react-native';
474
475
// Basic withTheme usage
476
class MyClassComponent extends React.Component {
477
render() {
478
const { theme } = this.props;
479
480
return (
481
<View style={{ backgroundColor: theme.colors.primary, padding: 20 }}>
482
<Text style={{ color: theme.colors.white }}>
483
Themed Class Component
484
</Text>
485
</View>
486
);
487
}
488
}
489
490
const ThemedComponent = withTheme(MyClassComponent);
491
492
// withTheme with component-specific overrides
493
class CustomButton extends React.Component {
494
render() {
495
const { theme, title, ...props } = this.props;
496
497
// Component gets theme.Button overrides automatically merged
498
return (
499
<TouchableOpacity
500
style={[
501
{
502
backgroundColor: theme.colors.primary,
503
borderRadius: 8,
504
paddingVertical: 12,
505
paddingHorizontal: 24,
506
},
507
theme.Button?.buttonStyle, // Merged automatically
508
props.buttonStyle,
509
]}
510
{...props}
511
>
512
<Text
513
style={[
514
{ color: theme.colors.white, fontSize: 16 },
515
theme.Button?.titleStyle, // Merged automatically
516
props.titleStyle,
517
]}
518
>
519
{title}
520
</Text>
521
</TouchableOpacity>
522
);
523
}
524
}
525
526
const ThemedButton = withTheme(CustomButton, 'Button');
527
528
// Functional component with withTheme
529
const FunctionalComponent = ({ theme, updateTheme }) => {
530
const togglePrimaryColor = () => {
531
updateTheme({
532
colors: {
533
...theme.colors,
534
primary: theme.colors.primary === '#007AFF' ? '#FF3B30' : '#007AFF',
535
},
536
});
537
};
538
539
return (
540
<View>
541
<Text style={{ color: theme.colors.black }}>
542
Current primary: {theme.colors.primary}
543
</Text>
544
<Button title="Toggle Color" onPress={togglePrimaryColor} />
545
</View>
546
);
547
};
548
549
const ThemedFunctionalComponent = withTheme(FunctionalComponent);
550
```
551
552
### ThemeConsumer & ThemeContext
553
554
Context consumer component and direct context access for advanced theming scenarios and render props pattern usage.
555
556
```typescript { .api }
557
/**
558
* Context consumer for accessing theme in render props pattern
559
*/
560
interface ThemeConsumerProps {
561
children: (themeContext: ThemeContextValue) => React.ReactElement;
562
}
563
564
/**
565
* React context for theme state
566
*/
567
const ThemeContext: React.Context<ThemeContextValue>;
568
```
569
570
**Usage Examples:**
571
572
```typescript
573
import React, { useContext } from 'react';
574
import { ThemeConsumer, ThemeContext } from 'react-native-elements';
575
576
// Using ThemeConsumer with render props
577
function RenderPropsComponent() {
578
return (
579
<ThemeConsumer>
580
{({ theme, updateTheme }) => (
581
<View style={{ backgroundColor: theme.colors.white, padding: 20 }}>
582
<Text style={{ color: theme.colors.black }}>
583
Consumer Component
584
</Text>
585
<Button
586
title="Update Theme"
587
onPress={() => updateTheme({
588
colors: { primary: '#FF6B6B' }
589
})}
590
/>
591
</View>
592
)}
593
</ThemeConsumer>
594
);
595
}
596
597
// Direct context access
598
function DirectContextComponent() {
599
const themeContext = useContext(ThemeContext);
600
601
if (!themeContext) {
602
throw new Error('Component must be wrapped with ThemeProvider');
603
}
604
605
const { theme, updateTheme, replaceTheme } = themeContext;
606
607
return (
608
<View style={{ backgroundColor: theme.colors.white }}>
609
<Text style={{ color: theme.colors.black }}>
610
Direct Context Access
611
</Text>
612
</View>
613
);
614
}
615
616
// Advanced theme management component
617
class ThemeManager extends React.Component {
618
render() {
619
return (
620
<ThemeConsumer>
621
{({ theme, updateTheme, replaceTheme }) => (
622
<View style={{ padding: 20 }}>
623
<Text style={{ fontSize: 18, marginBottom: 15 }}>
624
Theme Manager
625
</Text>
626
627
<Button
628
title="Light Theme"
629
onPress={() => replaceTheme(lightTheme)}
630
/>
631
632
<Button
633
title="Dark Theme"
634
onPress={() => replaceTheme(darkTheme)}
635
/>
636
637
<Button
638
title="Custom Primary"
639
onPress={() => updateTheme({
640
colors: { primary: '#9C27B0' }
641
})}
642
/>
643
</View>
644
)}
645
</ThemeConsumer>
646
);
647
}
648
}
649
```
650
651
### Default Colors
652
653
Built-in color palette providing the default theme colors for React Native Elements components.
654
655
```typescript { .api }
656
/**
657
* Default color palette for the theme
658
*/
659
const colors: Colors = {
660
primary: '#2089dc',
661
secondary: '#ca71eb',
662
white: '#ffffff',
663
black: '#242424',
664
grey0: '#393e42',
665
grey1: '#43484d',
666
grey2: '#5e6977',
667
grey3: '#86939e',
668
grey4: '#bdc6cf',
669
grey5: '#e1e8ed',
670
greyOutline: '#bbb',
671
searchBg: '#303337',
672
success: '#52c41a',
673
error: '#ff190c',
674
warning: '#faad14',
675
disabled: 'hsl(208, 8%, 90%)',
676
divider: '#bcbbc1',
677
platform: {
678
ios: {
679
primary: '#007aff',
680
secondary: '#5856d6',
681
grey: '#7d7d7d',
682
searchBg: '#dcdce1',
683
success: '#4cd964',
684
error: '#ff3b30',
685
warning: '#ffcc00',
686
},
687
android: {
688
primary: '#2196f3',
689
secondary: '#9c27b0',
690
grey: '#737373',
691
searchBg: '#dcdce1',
692
success: '#4caf50',
693
error: '#f44336',
694
warning: '#ffeb3b',
695
},
696
web: {
697
primary: '#2089dc',
698
secondary: '#ca71eb',
699
grey: '#393e42',
700
searchBg: '#303337',
701
success: '#52c41a',
702
error: '#ff190c',
703
warning: '#faad14',
704
},
705
},
706
};
707
```
708
709
**Usage Examples:**
710
711
```typescript
712
import { colors } from 'react-native-elements';
713
714
// Use default colors directly
715
const customTheme = {
716
colors: {
717
...colors,
718
primary: '#6366F1', // Override primary while keeping others
719
custom: '#FF6B6B', // Add custom colors
720
},
721
};
722
723
// Platform-specific color access
724
const platformPrimary = colors.platform.ios.primary;
725
const androidSuccess = colors.platform.android.success;
726
727
// Create variations of default colors
728
const lightTheme = {
729
colors: {
730
...colors,
731
white: '#ffffff',
732
black: '#000000',
733
},
734
};
735
736
const darkTheme = {
737
colors: {
738
...colors,
739
white: '#000000',
740
black: '#ffffff',
741
grey0: '#ffffff',
742
grey5: '#1c1c1e',
743
searchBg: '#1c1c1e',
744
},
745
};
746
```