1import { createSignal } from "solid-js";
2
3export const themeEvent = () => {
4 if (localStorage.getItem("theme") !== null) return;
5 const isDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
6 document.documentElement.classList.toggle("dark", isDark);
7};
8
9export const ThemeSelection = () => {
10 const [theme, setTheme] = createSignal(
11 localStorage.getItem("theme") === null ? "system"
12 : localStorage.theme === "dark" ? "dark"
13 : "light",
14 );
15
16 const updateTheme = (newTheme: string) => {
17 setTheme(newTheme);
18 document.documentElement.classList.toggle(
19 "dark",
20 newTheme === "dark" ||
21 (newTheme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches),
22 );
23 if (newTheme === "system") localStorage.removeItem("theme");
24 else localStorage.theme = newTheme;
25 };
26
27 const ThemeOption = (props: { theme: string; icon: string; label: string }) => {
28 return (
29 <button
30 classList={{
31 "flex items-center gap-2 rounded-xl border px-3 py-2": true,
32 "bg-neutral-200/60 border-neutral-300 dark:border-neutral-500 dark:bg-neutral-700":
33 theme() === props.theme,
34 "border-neutral-200 dark:border-neutral-600 hover:bg-neutral-200/30 dark:hover:bg-neutral-800":
35 theme() !== props.theme,
36 }}
37 onclick={() => updateTheme(props.theme)}
38 >
39 <span class={"iconify " + props.icon}></span>
40 <span>{props.label}</span>
41 </button>
42 );
43 };
44
45 return (
46 <div class="flex flex-col gap-0.5">
47 <label class="select-none">Theme</label>
48 <div class="flex gap-2">
49 <ThemeOption theme="system" icon="lucide--monitor" label="System" />
50 <ThemeOption theme="light" icon="lucide--sun" label="Light" />
51 <ThemeOption theme="dark" icon="lucide--moon" label="Dark" />
52 </div>
53 </div>
54 );
55};