0
# Theme System
1
2
The React JSS theme system provides comprehensive theming capabilities with providers, context access, and theme injection. It's essential for applications requiring consistent design systems and theme switching functionality.
3
4
## Capabilities
5
6
### ThemeProvider Component
7
8
Context provider that makes theme available to all child components.
9
10
```typescript { .api }
11
/**
12
* Theme context provider component
13
* Makes theme available to all child components via React context
14
*/
15
const ThemeProvider: ComponentType<{
16
/** Theme object to provide to child components */
17
theme: any;
18
/** Child components that will receive theme context */
19
children: ReactNode;
20
}>;
21
```
22
23
**Usage Examples:**
24
25
```typescript
26
import React from 'react';
27
import { ThemeProvider, createUseStyles } from 'react-jss';
28
29
const theme = {
30
colors: {
31
primary: '#007bff',
32
secondary: '#6c757d',
33
success: '#28a745',
34
danger: '#dc3545',
35
warning: '#ffc107',
36
info: '#17a2b8',
37
light: '#f8f9fa',
38
dark: '#343a40',
39
white: '#ffffff',
40
text: '#212529',
41
background: '#ffffff'
42
},
43
spacing: {
44
xs: '4px',
45
sm: '8px',
46
md: '16px',
47
lg: '24px',
48
xl: '32px',
49
xxl: '48px'
50
},
51
typography: {
52
fontFamily: '"Segoe UI", Tahoma, Geneva, Verdana, sans-serif',
53
fontSize: {
54
xs: '12px',
55
sm: '14px',
56
md: '16px',
57
lg: '18px',
58
xl: '20px',
59
xxl: '24px'
60
},
61
fontWeight: {
62
light: 300,
63
normal: 400,
64
medium: 500,
65
semibold: 600,
66
bold: 700
67
},
68
lineHeight: {
69
tight: 1.25,
70
normal: 1.5,
71
relaxed: 1.75
72
}
73
},
74
breakpoints: {
75
sm: '576px',
76
md: '768px',
77
lg: '992px',
78
xl: '1200px'
79
},
80
borderRadius: {
81
sm: '4px',
82
md: '8px',
83
lg: '12px',
84
xl: '16px'
85
},
86
shadows: {
87
sm: '0 1px 3px rgba(0,0,0,0.1)',
88
md: '0 4px 6px rgba(0,0,0,0.1)',
89
lg: '0 10px 25px rgba(0,0,0,0.1)',
90
xl: '0 20px 40px rgba(0,0,0,0.1)'
91
}
92
};
93
94
function App() {
95
return (
96
<ThemeProvider theme={theme}>
97
<MainContent />
98
</ThemeProvider>
99
);
100
}
101
```
102
103
### useTheme Hook
104
105
React hook to access the current theme from context.
106
107
```typescript { .api }
108
/**
109
* Hook to access current theme from context
110
* @returns Current theme object from ThemeProvider
111
*/
112
function useTheme<T = DefaultTheme>(): T;
113
```
114
115
**Usage Examples:**
116
117
```typescript
118
import React from 'react';
119
import { useTheme, createUseStyles } from 'react-jss';
120
121
const useStyles = createUseStyles({
122
container: {
123
padding: '20px',
124
borderRadius: '8px'
125
}
126
});
127
128
function ThemedComponent() {
129
const theme = useTheme();
130
const classes = useStyles();
131
132
return (
133
<div
134
className={classes.container}
135
style={{
136
backgroundColor: theme.colors.background,
137
color: theme.colors.text,
138
fontFamily: theme.typography.fontFamily
139
}}
140
>
141
<h1 style={{ color: theme.colors.primary }}>
142
Themed Component
143
</h1>
144
<p style={{ fontSize: theme.typography.fontSize.md }}>
145
This component uses theme values directly.
146
</p>
147
</div>
148
);
149
}
150
```
151
152
### withTheme Higher-Order Component
153
154
HOC that injects theme as a prop into the wrapped component.
155
156
```typescript { .api }
157
/**
158
* Higher-order component that injects theme as prop
159
* @param component - Component to wrap with theme injection
160
* @returns Component with theme prop injected
161
*/
162
function withTheme<P>(component: ComponentType<P>): ComponentType<P & {theme: any}>;
163
```
164
165
**Usage Examples:**
166
167
```typescript
168
import React from 'react';
169
import { withTheme } from 'react-jss';
170
171
const Button = ({ theme, children, variant = 'primary', ...props }) => {
172
const backgroundColor = theme.colors[variant] || theme.colors.primary;
173
174
return (
175
<button
176
style={{
177
padding: theme.spacing.md,
178
backgroundColor,
179
color: theme.colors.white,
180
border: 'none',
181
borderRadius: theme.borderRadius.md,
182
fontSize: theme.typography.fontSize.md,
183
fontWeight: theme.typography.fontWeight.medium,
184
cursor: 'pointer',
185
boxShadow: theme.shadows.sm,
186
transition: 'all 0.3s ease'
187
}}
188
{...props}
189
>
190
{children}
191
</button>
192
);
193
};
194
195
const ThemedButton = withTheme(Button);
196
197
// Usage
198
<ThemedButton variant="success">
199
Success Button
200
</ThemedButton>
201
```
202
203
### createTheming Function
204
205
Creates a custom theming context and utilities for more advanced theming scenarios.
206
207
```typescript { .api }
208
/**
209
* Creates custom theming context and utilities
210
* @param defaultTheme - Optional default theme object
211
* @returns Theming utilities object with custom context
212
*/
213
function createTheming<T>(defaultTheme?: T): Theming<T>;
214
215
interface Theming<Theme> {
216
/** Custom theme context */
217
context: Context<Theme>;
218
/** withTheme HOC using custom context */
219
withTheme: (component: ComponentType<any>) => ComponentType<any>;
220
/** useTheme hook using custom context */
221
useTheme: () => Theme;
222
/** ThemeProvider using custom context */
223
ThemeProvider: ComponentType<{theme: Theme; children: ReactNode}>;
224
}
225
```
226
227
**Usage Examples:**
228
229
```typescript
230
import React from 'react';
231
import { createTheming, createUseStyles } from 'react-jss';
232
233
// Create custom theming for a specific design system
234
const appTheming = createTheming({
235
brandColors: {
236
primary: '#ff6b6b',
237
secondary: '#4ecdc4',
238
accent: '#45b7d1'
239
},
240
spacing: {
241
small: '8px',
242
medium: '16px',
243
large: '24px'
244
}
245
});
246
247
const { ThemeProvider, useTheme, withTheme } = appTheming;
248
249
// Use the custom theming in styles
250
const useStyles = createUseStyles(
251
(theme) => ({
252
card: {
253
padding: theme.spacing.medium,
254
backgroundColor: theme.brandColors.primary,
255
borderRadius: '8px',
256
color: 'white'
257
}
258
}),
259
{ theming: appTheming }
260
);
261
262
function Card() {
263
const classes = useStyles();
264
const theme = useTheme();
265
266
return (
267
<div className={classes.card}>
268
<h3>Custom Themed Card</h3>
269
<p>Using brand color: {theme.brandColors.primary}</p>
270
</div>
271
);
272
}
273
274
function App() {
275
return (
276
<ThemeProvider theme={{
277
brandColors: {
278
primary: '#e74c3c',
279
secondary: '#3498db',
280
accent: '#f39c12'
281
},
282
spacing: {
283
small: '4px',
284
medium: '12px',
285
large: '20px'
286
}
287
}}>
288
<Card />
289
</ThemeProvider>
290
);
291
}
292
```
293
294
### Theme-Based Styles in createUseStyles
295
296
Use theme directly in style definitions:
297
298
```typescript
299
import React from 'react';
300
import { createUseStyles, ThemeProvider } from 'react-jss';
301
302
const useStyles = createUseStyles((theme) => ({
303
layout: {
304
fontFamily: theme.typography.fontFamily,
305
backgroundColor: theme.colors.background,
306
color: theme.colors.text,
307
minHeight: '100vh',
308
padding: theme.spacing.lg
309
},
310
header: {
311
backgroundColor: theme.colors.primary,
312
color: theme.colors.white,
313
padding: theme.spacing.md,
314
borderRadius: theme.borderRadius.md,
315
marginBottom: theme.spacing.lg,
316
boxShadow: theme.shadows.md,
317
'& h1': {
318
fontSize: theme.typography.fontSize.xxl,
319
fontWeight: theme.typography.fontWeight.bold,
320
margin: 0
321
}
322
},
323
content: {
324
backgroundColor: theme.colors.white,
325
padding: theme.spacing.lg,
326
borderRadius: theme.borderRadius.lg,
327
boxShadow: theme.shadows.sm,
328
'& p': {
329
fontSize: theme.typography.fontSize.md,
330
lineHeight: theme.typography.lineHeight.normal,
331
marginBottom: theme.spacing.md
332
}
333
},
334
button: {
335
backgroundColor: theme.colors.success,
336
color: theme.colors.white,
337
padding: `${theme.spacing.sm} ${theme.spacing.md}`,
338
border: 'none',
339
borderRadius: theme.borderRadius.sm,
340
fontSize: theme.typography.fontSize.md,
341
fontWeight: theme.typography.fontWeight.medium,
342
cursor: 'pointer',
343
boxShadow: theme.shadows.sm,
344
transition: 'all 0.3s ease',
345
'&:hover': {
346
backgroundColor: theme.colors.primary,
347
boxShadow: theme.shadows.md
348
}
349
}
350
}));
351
352
function ThemedLayout() {
353
const classes = useStyles();
354
355
return (
356
<div className={classes.layout}>
357
<header className={classes.header}>
358
<h1>Themed Application</h1>
359
</header>
360
<main className={classes.content}>
361
<p>This layout uses theme values for all styling.</p>
362
<button className={classes.button}>
363
Themed Button
364
</button>
365
</main>
366
</div>
367
);
368
}
369
```
370
371
### Dynamic Theme Switching
372
373
Implement theme switching functionality:
374
375
```typescript
376
import React, { useState } from 'react';
377
import { ThemeProvider, createUseStyles } from 'react-jss';
378
379
const lightTheme = {
380
colors: {
381
background: '#ffffff',
382
text: '#333333',
383
primary: '#007bff',
384
surface: '#f8f9fa'
385
}
386
};
387
388
const darkTheme = {
389
colors: {
390
background: '#1a1a1a',
391
text: '#ffffff',
392
primary: '#0d6efd',
393
surface: '#2d2d2d'
394
}
395
};
396
397
const useStyles = createUseStyles((theme) => ({
398
app: {
399
backgroundColor: theme.colors.background,
400
color: theme.colors.text,
401
minHeight: '100vh',
402
padding: '20px',
403
transition: 'all 0.3s ease'
404
},
405
card: {
406
backgroundColor: theme.colors.surface,
407
padding: '20px',
408
borderRadius: '8px',
409
marginBottom: '20px'
410
},
411
button: {
412
backgroundColor: theme.colors.primary,
413
color: 'white',
414
padding: '10px 20px',
415
border: 'none',
416
borderRadius: '4px',
417
cursor: 'pointer'
418
}
419
}));
420
421
function ThemedApp() {
422
const [isDark, setIsDark] = useState(false);
423
const theme = isDark ? darkTheme : lightTheme;
424
const classes = useStyles();
425
426
return (
427
<ThemeProvider theme={theme}>
428
<div className={classes.app}>
429
<div className={classes.card}>
430
<h1>Theme Switching Example</h1>
431
<p>Current theme: {isDark ? 'Dark' : 'Light'}</p>
432
<button
433
className={classes.button}
434
onClick={() => setIsDark(!isDark)}
435
>
436
Switch to {isDark ? 'Light' : 'Dark'} Theme
437
</button>
438
</div>
439
</div>
440
</ThemeProvider>
441
);
442
}
443
```
444
445
### TypeScript Theme Typing
446
447
Define strongly typed themes with TypeScript:
448
449
```typescript
450
import React from 'react';
451
import { ThemeProvider, createUseStyles } from 'react-jss';
452
453
// Define theme interface
454
interface AppTheme {
455
colors: {
456
primary: string;
457
secondary: string;
458
background: string;
459
text: string;
460
};
461
spacing: {
462
sm: string;
463
md: string;
464
lg: string;
465
};
466
typography: {
467
fontSize: {
468
sm: string;
469
md: string;
470
lg: string;
471
};
472
};
473
}
474
475
// Extend global theme interface
476
declare global {
477
namespace Jss {
478
interface Theme extends AppTheme {}
479
}
480
}
481
482
const theme: AppTheme = {
483
colors: {
484
primary: '#007bff',
485
secondary: '#6c757d',
486
background: '#ffffff',
487
text: '#333333'
488
},
489
spacing: {
490
sm: '8px',
491
md: '16px',
492
lg: '24px'
493
},
494
typography: {
495
fontSize: {
496
sm: '14px',
497
md: '16px',
498
lg: '20px'
499
}
500
}
501
};
502
503
const useStyles = createUseStyles<string, {}, AppTheme>((theme) => ({
504
container: {
505
padding: theme.spacing.md,
506
backgroundColor: theme.colors.background,
507
color: theme.colors.text
508
}
509
}));
510
511
function TypedThemedComponent() {
512
const classes = useStyles();
513
514
return (
515
<div className={classes.container}>
516
Strongly typed themed component
517
</div>
518
);
519
}
520
```
521
522
## Types
523
524
```typescript { .api }
525
type DefaultTheme = Jss.Theme;
526
527
interface Theming<Theme> {
528
context: Context<Theme>;
529
withTheme: (component: ComponentType<any>) => ComponentType<any>;
530
useTheme: () => Theme;
531
ThemeProvider: ComponentType<{theme: Theme; children: ReactNode}>;
532
}
533
534
declare global {
535
namespace Jss {
536
/** You can use the global Jss.Theme interface to define a project-wide default theme. */
537
export interface Theme {}
538
}
539
}
540
```