Reference
Options
createThemeToggle(element, {
themes: ['light', 'dark'],
fallback: 'light',
storageKey: 'theme',
attribute: 'class',
colorScheme: true,
themeColor: undefined,
disableTransitions: true,
variant: 'segmented',
system: true,
labels: false,
});
| Option | Default | |
|---|---|---|
themes |
['light','dark'] |
Any names you like — ['light','dark','sepia']. |
fallback |
'light' |
What system means when the machine says nothing. |
dark |
names containing "dark" | Which themes count as dark, for color-scheme. |
storageKey |
'theme' |
|
remember |
true |
false keeps the choice for the page only. |
attribute |
'class' |
An attribute name, or a list of them. |
element |
<html> |
|
colorScheme |
true |
Sets color-scheme, so native controls follow too. |
themeColor |
— | { light: '#fff', dark: '#101014' } for the browser chrome. |
disableTransitions |
true |
Stops the page animating every colour at once. |
variant |
'segmented' |
Or 'button', which cycles. |
system |
true |
Offer system as a choice. |
labels |
false |
Show the name beside the icon. |
icons |
— | Your own markup per theme. |
theme |
— | An existing controller to drive, instead of making one. |
color-scheme is not optional
createThemeToggle(el); // sets color-scheme by default
Without it, a dark page still has white scrollbars, a white caret, white
<select> dropdowns and white date pickers. color-scheme is what tells the
browser to render its own parts dark, and it is the single most-forgotten
line in a dark theme.
theme-color is what people actually see on a phone
createThemeToggle(el, { themeColor: { light: '#ffffff', dark: '#101014' } });
On mobile this colours the browser's chrome around your page — the largest visible surface after the page itself. A dark site with a white bar above it looks broken.
If the page has no <meta name="theme-color">, one is created. If it has one, it
is updated. Tags with a media attribute are left alone, because those are
already doing this job.
Why transitions are suppressed
A stylesheet with transition: background .2s on many elements turns a theme
switch into a two-hundred-millisecond smear of every colour on the page at once.
While switching, a transition: none rule is added, the change is made, a reflow
is forced so the rule certainly applied, and the rule is removed. The theme
changes instantly; everything else keeps its transitions.
disableTransitions: false if you have designed for the smear.
Named themes
createThemeToggle(el, {
themes: ['light', 'dark', 'sepia', 'high-contrast'],
attribute: 'data-theme',
dark: ['dark', 'high-contrast'],
});
dark decides which of them get color-scheme: dark; by default it is any theme
with "dark" in its name. Remember to pass the same themes to
antiFlashScript(), or the snippet will not recognise a stored sepia and will
fall back to the system.
Driving one controller from several places
import { createTheme, createThemeToggle } from '@devix-labs/theme-toggle';
const theme = createTheme({ themeColor: { light: '#fff', dark: '#101014' } });
createThemeToggle(header, { theme });
createThemeToggle(footer, { theme });
Both controls stay in step, and destroy() on either leaves the shared
controller alone — only the one that created it disposes of it.