|
4 | 4 | */ |
5 | 5 |
|
6 | 6 | (() => { |
| 7 | + // Theme states |
| 8 | + const THEME = { |
| 9 | + dark: 'is-dark', |
| 10 | + light: 'is-light', |
| 11 | + system: 'is-system', |
| 12 | + } |
| 13 | + |
| 14 | + // Method to change the class on the <html> element |
| 15 | + const applyClass = (value) => { |
| 16 | + html.classList.remove(THEME.dark, THEME.light, THEME.system) |
| 17 | + html.classList.add(value) |
| 18 | + } |
7 | 19 |
|
8 | | - // Switcher toggle |
| 20 | + // Variables |
| 21 | + const html = document.documentElement |
| 22 | + const matchMedia = window.matchMedia('(prefers-color-scheme:dark)') |
9 | 23 | const switcher = document.getElementById('color-scheme-switch') |
| 24 | + |
10 | 25 | if (switcher) { |
11 | | - const html = document.documentElement |
12 | | - const theme = localStorage.getItem('theme') !== undefined ? localStorage.getItem('theme') : 'is-light' |
13 | | - |
14 | | - switcher.checked = theme === 'is-dark' ? true : false |
15 | | - |
16 | | - switcher.addEventListener('change', () => { |
17 | | - if (switcher.checked) { |
18 | | - localStorage.setItem('theme', 'is-dark') |
19 | | - html.classList.add('is-dark') |
20 | | - } else { |
21 | | - localStorage.setItem('theme', 'is-light') |
22 | | - html.classList.remove('is-dark') |
23 | | - } |
| 26 | + const colourScheme = matchMedia.matches ? THEME.dark : THEME.light |
| 27 | + const storedTheme = localStorage.getItem('theme') !== null ? localStorage.getItem('theme') : THEME.system |
| 28 | + |
| 29 | + // Set the default input to be checked |
| 30 | + if (storedTheme !== THEME.system) { |
| 31 | + switcher.querySelector(`input[value="${storedTheme}"]`).checked = true |
| 32 | + applyClass(storedTheme) |
| 33 | + } else { |
| 34 | + // Set default theme |
| 35 | + switcher.querySelector(`input[value="${THEME.system}"]`).checked = true |
| 36 | + matchMedia.matches ? applyClass(THEME.dark) : applyClass(THEME.light) |
| 37 | + } |
| 38 | + |
| 39 | + // Loop through all switcher inputs |
| 40 | + switcher.querySelectorAll('input').forEach((input) => { |
| 41 | + input.addEventListener('change', ({ target }) => { |
| 42 | + if (target.value === THEME.dark || target.value === THEME.light) { |
| 43 | + localStorage.setItem('theme', target.value) |
| 44 | + applyClass(target.value) |
| 45 | + } else { |
| 46 | + localStorage.setItem('theme', THEME.system) |
| 47 | + applyClass(colourScheme) |
| 48 | + } |
| 49 | + }) |
24 | 50 | }) |
| 51 | + } else { |
| 52 | + // Set default theme |
| 53 | + matchMedia.matches ? applyClass(THEME.dark) : applyClass(THEME.light) |
25 | 54 | } |
26 | 55 |
|
| 56 | + // Listen for changes made to the system |
| 57 | + matchMedia.addListener((event) => { |
| 58 | + // If the switcher is disabled or enabled BUT set to the system preference, change the theme |
| 59 | + // The theme will not change if it has manually been set by the switcher |
| 60 | + if (!switcher || (switcher && switcher.querySelector(`input[value="${THEME.system}"]`).checked)) { |
| 61 | + return event.matches ? applyClass(THEME.dark) : applyClass(THEME.light) |
| 62 | + } |
| 63 | + }) |
| 64 | + |
27 | 65 | })() |
0 commit comments