|
12 | 12 | import Tooltip from './Tooltip.svelte';
|
13 | 13 |
|
14 | 14 | import { cls } from '../utils/styles';
|
| 15 | + import { getSettings } from './settings'; |
15 | 16 |
|
16 |
| - export let darkThemes = ['dark']; |
17 |
| - export let lightThemes = ['light']; |
| 17 | + const { currentTheme, themes: allThemes } = getSettings(); |
18 | 18 |
|
19 |
| - let open = false; |
20 |
| -
|
21 |
| - $: themes = colorScheme === 'dark' ? darkThemes : lightThemes; |
22 |
| -
|
23 |
| - let theme: (typeof themes)[number] | null = localStorage.theme ?? 'system'; |
| 19 | + /** The list of dark themes to chose from, if not the list provided to `settings`. */ |
| 20 | + export let darkThemes = allThemes?.dark ?? ['dark']; |
| 21 | + /** The list of light themes to chose from, if not the list provided to `settings`. */ |
| 22 | + export let lightThemes = allThemes?.light ?? ['light']; |
24 | 23 |
|
25 |
| - let colorScheme: 'light' | 'dark' = |
26 |
| - (theme !== 'system' && darkThemes.includes(theme)) || |
27 |
| - (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches) |
28 |
| - ? 'dark' |
29 |
| - : 'light'; |
30 |
| -
|
31 |
| - // TODO: Call inline in `head` to avoid FOUC. Move to <Theme>? |
32 |
| - function setTheme(themeName: typeof theme) { |
33 |
| - if (themeName === 'system') { |
34 |
| - // Remove setting |
35 |
| - localStorage.removeItem('theme'); |
36 |
| - delete document.documentElement.dataset.theme; |
37 |
| -
|
38 |
| - if (window.matchMedia('(prefers-color-scheme: dark)').matches) { |
39 |
| - document.documentElement.classList.add('dark'); |
40 |
| - } |
41 |
| - } else { |
42 |
| - // Save theme to local storage, set `<html data-theme="">`, and set `<html class="dark">` if dark mode |
43 |
| - localStorage.theme = themeName; |
44 |
| - document.documentElement.dataset.theme = theme; |
| 24 | + let open = false; |
45 | 25 |
|
46 |
| - if (darkThemes.includes(themeName)) { |
47 |
| - colorScheme = 'dark'; |
48 |
| - document.documentElement.classList.add('dark'); |
49 |
| - } else { |
50 |
| - colorScheme = 'light'; |
51 |
| - document.documentElement.classList.remove('dark'); |
52 |
| - } |
53 |
| - } |
54 |
| - } |
55 |
| - $: setTheme(theme); |
| 26 | + $: themes = $currentTheme.dark ? darkThemes : lightThemes; |
56 | 27 |
|
57 | 28 | function onKeyDown(e: KeyboardEvent) {
|
58 | 29 | if (e.ctrlKey && e.code === 'KeyT') {
|
59 | 30 | if (e.shiftKey) {
|
60 | 31 | // Pick next theme
|
61 |
| - const currentIndex = themes.indexOf(theme); |
62 |
| - theme = themes[(currentIndex + 1) % themes.length]; |
| 32 | + const currentIndex = themes.indexOf($currentTheme.resolvedTheme); |
| 33 | + let newTheme = themes[(currentIndex + 1) % themes.length]; |
| 34 | + currentTheme.setTheme(newTheme); |
63 | 35 | } else {
|
64 | 36 | // Toggle light/dark
|
65 |
| - colorScheme = colorScheme === 'light' ? 'dark' : 'light'; |
66 |
| - theme = colorScheme; |
| 37 | + let newTheme = $currentTheme.dark ? 'light' : 'dark'; |
| 38 | + currentTheme.setTheme(newTheme); |
67 | 39 | }
|
68 | 40 | }
|
69 | 41 | }
|
|
77 | 49 | >
|
78 | 50 | Mode
|
79 | 51 |
|
80 |
| - {#if theme !== 'system'} |
| 52 | + {#if $currentTheme.theme} |
81 | 53 | <span transition:fly={{ x: 8 }}>
|
82 | 54 | <Tooltip title="Reset to System" offset={2}>
|
83 | 55 | <Button
|
|
86 | 58 | size="sm"
|
87 | 59 | class="mr-1"
|
88 | 60 | on:click={() => {
|
89 |
| - colorScheme = window.matchMedia('(prefers-color-scheme: dark)').matches |
90 |
| - ? 'dark' |
91 |
| - : 'light'; |
92 |
| - theme = 'system'; |
| 61 | + currentTheme.setTheme('system'); |
93 | 62 | }}
|
94 | 63 | />
|
95 | 64 | </Tooltip>
|
|
98 | 67 |
|
99 | 68 | <Switch
|
100 | 69 | id="switch-color-scheme"
|
101 |
| - checked={colorScheme === 'light'} |
| 70 | + checked={!$currentTheme.dark} |
102 | 71 | on:change={(e) => {
|
103 |
| - colorScheme = e.target?.checked ? 'light' : 'dark'; |
104 |
| - theme = colorScheme; |
| 72 | + let newTheme = e.target?.checked ? 'light' : 'dark'; |
| 73 | + currentTheme.setTheme(newTheme); |
105 | 74 | }}
|
106 | 75 | class="my-1"
|
107 | 76 | let:checked
|
|
117 | 86 | <div class="grid grid-cols-2 gap-2 p-2 border-b border-surface-content/10">
|
118 | 87 | {#each themes as themeName}
|
119 | 88 | <MenuItem
|
120 |
| - on:click={() => (theme = themeName)} |
| 89 | + on:click={() => currentTheme.setTheme(themeName)} |
121 | 90 | data-theme={themeName}
|
122 | 91 | class={cls(
|
123 | 92 | 'bg-surface-100 text-surface-content font-semibold border shadow',
|
124 |
| - theme === themeName && 'ring-2 ring-surface-content' |
| 93 | + $currentTheme.resolvedTheme === themeName && 'ring-2 ring-surface-content' |
125 | 94 | )}
|
126 | 95 | >
|
127 | 96 | <div class="grid gap-1">
|
|
0 commit comments