|
1 | 1 | import { useEffect, useState } from "react"; |
2 | 2 |
|
3 | | -type DarkModeOptions = "custom-dark" | "light" | "system"; |
| 3 | +type ThemeOptions = "custom-dark" | "light" | "system"; |
4 | 4 |
|
5 | | -export function DarkModeDropdown() { |
6 | | - const [darkModeOption, setDarkModeOption] = |
7 | | - useState<DarkModeOptions>("light"); |
| 5 | +export function ThemeSelector() { |
| 6 | + const [selectedTheme, setSelectedTheme] = useState<ThemeOptions | undefined>( |
| 7 | + undefined |
| 8 | + ); |
8 | 9 |
|
9 | 10 | useEffect(() => { |
10 | | - if ( |
11 | | - localStorage.theme === "light" || |
12 | | - (!("theme" in localStorage) && |
13 | | - !window.matchMedia("(prefers-color-scheme:dark)").matches) |
14 | | - ) { |
15 | | - setDocumentElement("light"); |
16 | | - } else { |
17 | | - setDocumentElement("custom-dark"); |
| 11 | + const theme = localStorage.getItem("theme") as ThemeOptions; |
| 12 | + if (theme) { |
| 13 | + setSelectedTheme(theme); |
18 | 14 | } |
19 | 15 | }, []); |
20 | 16 |
|
21 | 17 | function onClick($event: React.MouseEvent<HTMLLIElement>) { |
22 | 18 | $event.stopPropagation(); |
23 | 19 | const li = $event.currentTarget as HTMLLIElement; |
24 | | - setDocumentElement(li.id as DarkModeOptions); |
| 20 | + setDocumentElement(li.id as ThemeOptions); |
25 | 21 | } |
26 | 22 |
|
27 | | - const setDocumentElement = (theme: DarkModeOptions) => { |
28 | | - setDarkModeOption(theme); |
29 | | - theme === "system" |
30 | | - ? setSystemPreferenceTheme() |
31 | | - : setLightOrDarkTheme(theme); |
| 23 | + const setDocumentElement = (theme: ThemeOptions) => { |
| 24 | + setSelectedTheme(theme); |
| 25 | + theme === "system" ? setSystemPreferenceTheme() : setTheme(theme); |
32 | 26 | }; |
33 | 27 |
|
34 | | - const buttonIcon = getButtonIconByOption(darkModeOption); |
| 28 | + const buttonIcon = getButtonIconByOption(selectedTheme); |
35 | 29 |
|
36 | 30 | return ( |
37 | 31 | <> |
38 | 32 | <div className="dropdown dropdown-bottom dropdown-end"> |
39 | 33 | <label |
40 | 34 | tabIndex={0} |
41 | 35 | className="btn btn-circle btn-ghost m-1" |
42 | | - data-testid="darkModeButton" |
| 36 | + data-testid="themeSelectorButton" |
43 | 37 | > |
44 | 38 | {buttonIcon} |
45 | 39 | </label> |
@@ -119,30 +113,26 @@ const SystemPreference = () => ( |
119 | 113 | </svg> |
120 | 114 | ); |
121 | 115 |
|
122 | | -const getButtonIconByOption = (option: DarkModeOptions) => { |
| 116 | +const getButtonIconByOption = (option: ThemeOptions | undefined) => { |
123 | 117 | switch (option) { |
124 | | - case "light": { |
| 118 | + case "light": |
125 | 119 | return <LightMode />; |
126 | | - } |
127 | | - case "custom-dark": { |
| 120 | + |
| 121 | + case "custom-dark": |
128 | 122 | return <DarkMode />; |
129 | | - } |
130 | | - case "system": { |
| 123 | + |
| 124 | + default: |
131 | 125 | return <SystemPreference />; |
132 | | - } |
133 | 126 | } |
134 | 127 | }; |
135 | 128 |
|
136 | 129 | const setSystemPreferenceTheme = () => { |
137 | 130 | const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches; |
| 131 | + setTheme(isDark ? "custom-dark" : "light"); |
138 | 132 | localStorage.removeItem("theme"); |
139 | | - document.documentElement.dataset.theme = isDark ? "custom-dark" : "light"; |
140 | | - isDark |
141 | | - ? document.documentElement.classList.add("dark") |
142 | | - : document.documentElement.classList.remove("dark"); |
143 | 133 | }; |
144 | 134 |
|
145 | | -const setLightOrDarkTheme = (theme: "custom-dark" | "light") => { |
| 135 | +const setTheme = (theme: "custom-dark" | "light") => { |
146 | 136 | localStorage.theme = theme; |
147 | 137 | document.documentElement.dataset.theme = theme; |
148 | 138 | theme === "custom-dark" |
|
0 commit comments