0
# Theme System
1
2
Built-in themes and utilities for creating custom themes for the CodeMirror editor. The theme system provides light, dark, and no-theme variants out of the box, plus full support for custom theme creation.
3
4
## Capabilities
5
6
### Built-in Light Theme
7
8
Default light theme with clean styling optimized for readability.
9
10
```typescript { .api }
11
/**
12
* Default light theme extension with white background
13
* Provides clean, minimal styling for light environments
14
*/
15
const defaultLightThemeOption: Extension;
16
```
17
18
**Usage Examples:**
19
20
```typescript
21
import CodeMirror from "@uiw/react-codemirror";
22
import { defaultLightThemeOption } from "@uiw/react-codemirror";
23
24
// Using the built-in light theme directly
25
function LightThemedEditor() {
26
return (
27
<CodeMirror
28
value="// Light theme example"
29
theme={defaultLightThemeOption}
30
height="200px"
31
/>
32
);
33
}
34
35
// Using string shorthand (equivalent)
36
function LightThemedEditorShorthand() {
37
return (
38
<CodeMirror
39
value="// Light theme example"
40
theme="light"
41
height="200px"
42
/>
43
);
44
}
45
```
46
47
### Built-in Dark Theme
48
49
One Dark theme imported from CodeMirror's official theme collection.
50
51
```typescript { .api }
52
/**
53
* One Dark theme extension (re-exported from @codemirror/theme-one-dark)
54
* Popular dark theme with purple-blue accent colors
55
*/
56
const oneDark: Extension;
57
```
58
59
**Usage Examples:**
60
61
```typescript
62
import CodeMirror from "@uiw/react-codemirror";
63
import { oneDark } from "@uiw/react-codemirror";
64
65
// Using the built-in dark theme directly
66
function DarkThemedEditor() {
67
return (
68
<CodeMirror
69
value="// Dark theme example"
70
theme={oneDark}
71
height="200px"
72
/>
73
);
74
}
75
76
// Using string shorthand (equivalent)
77
function DarkThemedEditorShorthand() {
78
return (
79
<CodeMirror
80
value="// Dark theme example"
81
theme="dark"
82
height="200px"
83
/>
84
);
85
}
86
```
87
88
### No Theme Option
89
90
Option to disable all built-in theming and use only manually provided theme extensions.
91
92
```typescript { .api }
93
/**
94
* No theme option - disables all built-in themes
95
* Use when you want complete control over styling via custom extensions
96
*/
97
theme: 'none'
98
```
99
100
**Usage Examples:**
101
102
```typescript
103
import React from "react";
104
import CodeMirror from "@uiw/react-codemirror";
105
import { EditorView } from "@codemirror/view";
106
107
// Using no theme - completely unstyled
108
function UnstyledEditor() {
109
return (
110
<CodeMirror
111
value="// No built-in theme applied"
112
theme="none"
113
height="200px"
114
/>
115
);
116
}
117
118
// Using no theme with custom styling
119
function CustomStyledEditor() {
120
const customTheme = EditorView.theme({
121
'&': {
122
backgroundColor: '#f8f9fa',
123
color: '#343a40',
124
},
125
'.cm-content': {
126
fontFamily: 'Monaco, monospace',
127
fontSize: '14px',
128
},
129
});
130
131
return (
132
<CodeMirror
133
value="// Custom styled editor"
134
theme="none"
135
extensions={[customTheme]}
136
height="200px"
137
/>
138
);
139
}
140
```
141
142
### Custom Theme Creation
143
144
Support for creating completely custom themes using CodeMirror's theme system.
145
146
**Usage Examples:**
147
148
```typescript
149
import React from "react";
150
import CodeMirror from "@uiw/react-codemirror";
151
import { EditorView } from "@codemirror/view";
152
import { javascript } from "@codemirror/lang-javascript";
153
154
// Creating a custom theme
155
function CustomThemedEditor() {
156
const customTheme = EditorView.theme({
157
// Editor container
158
'&': {
159
color: '#2d3748',
160
backgroundColor: '#f7fafc',
161
fontSize: '14px',
162
fontFamily: 'Consolas, "Liberation Mono", Menlo, Courier, monospace',
163
},
164
165
// Content area
166
'.cm-content': {
167
padding: '16px',
168
minHeight: '100px',
169
caretColor: '#4299e1',
170
},
171
172
// Cursor and selection
173
'.cm-cursor, .cm-dropCursor': {
174
borderLeftColor: '#4299e1',
175
borderLeftWidth: '2px',
176
},
177
178
'.cm-focused .cm-selectionBackground, ::selection': {
179
backgroundColor: '#bee3f8',
180
},
181
182
// Line numbers
183
'.cm-gutters': {
184
backgroundColor: '#edf2f7',
185
color: '#a0aec0',
186
border: 'none',
187
borderRight: '1px solid #e2e8f0',
188
},
189
190
'.cm-activeLineGutter': {
191
backgroundColor: '#e2e8f0',
192
color: '#4a5568',
193
},
194
195
// Active line
196
'.cm-activeLine': {
197
backgroundColor: '#f1f5f9',
198
},
199
200
// Matching brackets
201
'.cm-matchingBracket': {
202
backgroundColor: '#fed7d7',
203
outline: '1px solid #fc8181',
204
},
205
206
// Search highlighting
207
'.cm-searchMatch': {
208
backgroundColor: '#fef5e7',
209
outline: '1px solid #f6ad55',
210
},
211
212
'.cm-searchMatch.cm-searchMatch-selected': {
213
backgroundColor: '#fbd38d',
214
},
215
});
216
217
return (
218
<CodeMirror
219
value={`// Custom themed editor
220
const greeting = "Hello World!";
221
console.log(greeting);
222
223
function add(a, b) {
224
return a + b;
225
}`}
226
theme={customTheme}
227
extensions={[javascript()]}
228
height="250px"
229
/>
230
);
231
}
232
233
// Creating a high-contrast theme
234
function HighContrastEditor() {
235
const highContrastTheme = EditorView.theme({
236
'&': {
237
color: '#000000',
238
backgroundColor: '#ffffff',
239
fontSize: '16px',
240
fontWeight: 'bold',
241
},
242
243
'.cm-content': {
244
padding: '20px',
245
caretColor: '#000000',
246
},
247
248
'.cm-cursor': {
249
borderLeftColor: '#000000',
250
borderLeftWidth: '3px',
251
},
252
253
'.cm-focused .cm-selectionBackground': {
254
backgroundColor: '#ffff00',
255
color: '#000000',
256
},
257
258
'.cm-gutters': {
259
backgroundColor: '#f0f0f0',
260
color: '#000000',
261
borderRight: '2px solid #000000',
262
fontWeight: 'bold',
263
},
264
265
'.cm-activeLine': {
266
backgroundColor: '#ffffcc',
267
},
268
269
'.cm-matchingBracket': {
270
backgroundColor: '#ff0000',
271
color: '#ffffff',
272
fontWeight: 'bold',
273
},
274
});
275
276
return (
277
<CodeMirror
278
value="// High contrast theme for accessibility"
279
theme={highContrastTheme}
280
height="150px"
281
/>
282
);
283
}
284
```
285
286
### Theme Switching
287
288
Dynamic theme switching functionality for user preferences.
289
290
**Usage Examples:**
291
292
```typescript
293
import React, { useState } from "react";
294
import CodeMirror from "@uiw/react-codemirror";
295
import { oneDark, defaultLightThemeOption } from "@uiw/react-codemirror";
296
import { EditorView } from "@codemirror/view";
297
298
function ThemeSwitchingEditor() {
299
const [currentTheme, setCurrentTheme] = useState('light');
300
301
const themes = {
302
light: defaultLightThemeOption,
303
dark: oneDark,
304
custom: EditorView.theme({
305
'&': {
306
color: '#2d5016',
307
backgroundColor: '#f0fff4',
308
},
309
'.cm-content': {
310
caretColor: '#22543d',
311
},
312
'.cm-focused .cm-selectionBackground': {
313
backgroundColor: '#c6f6d5',
314
},
315
'.cm-gutters': {
316
backgroundColor: '#e6fffa',
317
color: '#2d5016',
318
},
319
}),
320
};
321
322
return (
323
<div>
324
<div style={{ marginBottom: 10 }}>
325
<label>
326
Theme:
327
<select
328
value={currentTheme}
329
onChange={(e) => setCurrentTheme(e.target.value)}
330
style={{ marginLeft: 8 }}
331
>
332
<option value="light">Light</option>
333
<option value="dark">Dark</option>
334
<option value="custom">Custom Green</option>
335
</select>
336
</label>
337
</div>
338
339
<CodeMirror
340
value={`// Theme switching demo
341
// Current theme: ${currentTheme}
342
const message = "Switch themes using the dropdown above";
343
console.log(message);`}
344
theme={themes[currentTheme]}
345
height="200px"
346
/>
347
</div>
348
);
349
}
350
351
// System theme detection
352
function SystemThemeEditor() {
353
const [theme, setTheme] = useState(() => {
354
// Detect system preference
355
if (typeof window !== 'undefined') {
356
return window.matchMedia('(prefers-color-scheme: dark)').matches
357
? 'dark'
358
: 'light';
359
}
360
return 'light';
361
});
362
363
React.useEffect(() => {
364
if (typeof window !== 'undefined') {
365
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
366
367
const handleChange = () => {
368
setTheme(mediaQuery.matches ? 'dark' : 'light');
369
};
370
371
mediaQuery.addListener(handleChange);
372
return () => mediaQuery.removeListener(handleChange);
373
}
374
}, []);
375
376
return (
377
<div>
378
<div style={{ marginBottom: 10 }}>
379
Current theme: {theme} (auto-detected from system)
380
</div>
381
382
<CodeMirror
383
value="// This editor follows your system theme preference"
384
theme={theme}
385
height="150px"
386
/>
387
</div>
388
);
389
}
390
```
391
392
### Theme Inheritance and Customization
393
394
Extending existing themes with additional styling.
395
396
**Usage Examples:**
397
398
```typescript
399
import React from "react";
400
import CodeMirror from "@uiw/react-codemirror";
401
import { oneDark } from "@uiw/react-codemirror";
402
import { EditorView } from "@codemirror/view";
403
404
function ExtendedThemeEditor() {
405
// Extend the dark theme with custom additions
406
const extendedDarkTheme = [
407
oneDark, // Base dark theme
408
EditorView.theme({
409
// Additional customizations
410
'.cm-content': {
411
fontSize: '16px',
412
lineHeight: '1.6',
413
fontFamily: '"Fira Code", monospace',
414
},
415
416
'.cm-gutters': {
417
fontSize: '14px',
418
},
419
420
// Custom class for highlighted comments
421
'.cm-comment': {
422
fontStyle: 'italic',
423
opacity: '0.8',
424
},
425
426
// Custom scrollbar (webkit browsers)
427
'.cm-scroller::-webkit-scrollbar': {
428
width: '8px',
429
},
430
431
'.cm-scroller::-webkit-scrollbar-track': {
432
background: '#1e1e1e',
433
},
434
435
'.cm-scroller::-webkit-scrollbar-thumb': {
436
background: '#4a4a4a',
437
borderRadius: '4px',
438
},
439
440
'.cm-scroller::-webkit-scrollbar-thumb:hover': {
441
background: '#5a5a5a',
442
},
443
}),
444
];
445
446
return (
447
<CodeMirror
448
value={`// Extended dark theme with custom font and scrollbar
449
// This comment should appear italic
450
const code = "Beautiful syntax highlighting";
451
console.log(code);`}
452
theme={extendedDarkTheme}
453
height="200px"
454
/>
455
);
456
}
457
458
// Theme with CSS variables for dynamic customization
459
function VariableThemeEditor() {
460
const [primaryColor, setPrimaryColor] = useState('#4299e1');
461
462
const variableTheme = EditorView.theme({
463
'&': {
464
'--primary-color': primaryColor,
465
'--primary-light': primaryColor + '20',
466
'--primary-dark': primaryColor + 'dd',
467
},
468
469
'.cm-content': {
470
caretColor: 'var(--primary-color)',
471
},
472
473
'.cm-focused .cm-selectionBackground': {
474
backgroundColor: 'var(--primary-light)',
475
},
476
477
'.cm-cursor': {
478
borderLeftColor: 'var(--primary-color)',
479
},
480
481
'.cm-activeLine': {
482
backgroundColor: 'var(--primary-light)',
483
},
484
485
'.cm-matchingBracket': {
486
backgroundColor: 'var(--primary-dark)',
487
color: 'white',
488
},
489
});
490
491
return (
492
<div>
493
<div style={{ marginBottom: 10 }}>
494
<label>
495
Primary Color:
496
<input
497
type="color"
498
value={primaryColor}
499
onChange={(e) => setPrimaryColor(e.target.value)}
500
style={{ marginLeft: 8 }}
501
/>
502
</label>
503
</div>
504
505
<CodeMirror
506
value="// Dynamic theme with CSS variables"
507
theme={variableTheme}
508
height="150px"
509
/>
510
</div>
511
);
512
}
513
```