an atproto based link aggregator
at main 56 lines 1.5 kB view raw
1<script lang="ts"> 2 import { browser } from '$app/environment'; 3 4 let dark = $state(false); 5 6 // Initialize from localStorage or system preference 7 if (browser) { 8 const stored = localStorage.getItem('theme'); 9 if (stored) { 10 dark = stored === 'dark'; 11 } else { 12 dark = window.matchMedia('(prefers-color-scheme: dark)').matches; 13 } 14 updateTheme(); 15 } 16 17 function updateTheme() { 18 if (dark) { 19 document.documentElement.classList.add('dark'); 20 } else { 21 document.documentElement.classList.remove('dark'); 22 } 23 } 24 25 function toggle() { 26 dark = !dark; 27 localStorage.setItem('theme', dark ? 'dark' : 'light'); 28 updateTheme(); 29 } 30</script> 31 32<button 33 onclick={toggle} 34 class="rounded-lg p-2 hover:bg-gray-100 dark:hover:bg-gray-800" 35 aria-label={dark ? 'Switch to light mode' : 'Switch to dark mode'} 36> 37 {#if dark} 38 <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> 39 <path 40 stroke-linecap="round" 41 stroke-linejoin="round" 42 stroke-width="2" 43 d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" 44 /> 45 </svg> 46 {:else} 47 <svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor"> 48 <path 49 stroke-linecap="round" 50 stroke-linejoin="round" 51 stroke-width="2" 52 d="M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z" 53 /> 54 </svg> 55 {/if} 56</button>