atproto explorer pdsls.dev
atproto tool
at main 1.9 kB view raw
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};