A frontend for your PDS
at main 98 lines 2.9 kB view raw
1<script lang="ts"> 2 import { onMount } from 'svelte'; 3 import { isDark } from './theme'; 4 5 // onMount: initialise the store value 6 onMount(() => { 7 const saved = localStorage.getItem('darkMode'); 8 if (saved !== null) { 9 isDark.set(saved === 'true'); 10 } else { 11 isDark.set(window.matchMedia('(prefers-color-scheme: dark)').matches); 12 } 13 applyTheme(); 14 }); 15 16 function applyTheme() { 17 $isDark 18 ? document.documentElement.classList.add('dark') 19 : document.documentElement.classList.remove('dark'); 20 } 21 22 function toggleDarkMode() { 23 isDark.update(v => { 24 const next = !v; 25 localStorage.setItem('darkMode', next.toString()); 26 return next; 27 }); 28 applyTheme(); 29 } 30</script> 31 32<button 33 type="button" 34 class="dark-mode-toggle" 35 onclick={toggleDarkMode} 36 aria-label={isDark ? 'Switch to light mode' : 'Switch to dark mode'} 37 title={isDark ? 'Switch to light mode' : 'Switch to dark mode'} 38> 39 {#if isDark} 40 <!-- Sun icon for light mode --> 41 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 42 <circle cx="12" cy="12" r="5"></circle> 43 <line x1="12" y1="1" x2="12" y2="3"></line> 44 <line x1="12" y1="21" x2="12" y2="23"></line> 45 <line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line> 46 <line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line> 47 <line x1="1" y1="12" x2="3" y2="12"></line> 48 <line x1="21" y1="12" x2="23" y2="12"></line> 49 <line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line> 50 <line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line> 51 </svg> 52 {:else} 53 <!-- Moon icon for dark mode --> 54 <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> 55 <path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path> 56 </svg> 57 {/if} 58</button> 59 60<style> 61 .dark-mode-toggle { 62 position: fixed; 63 bottom: 24px; 64 right: 24px; 65 width: 48px; 66 height: 48px; 67 border-radius: 50%; 68 border: 1px solid var(--border-color); 69 background-color: var(--content-background-color); 70 color: var(--text-color); 71 cursor: pointer; 72 display: flex; 73 align-items: center; 74 justify-content: center; 75 box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); 76 transition: all 0.2s ease; 77 z-index: 100; 78 } 79 80 .dark-mode-toggle:hover { 81 transform: scale(1.1); 82 box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); 83 } 84 85 .dark-mode-toggle:focus-visible { 86 outline: 2px solid var(--link-color); 87 outline-offset: 2px; 88 } 89 90 @media screen and (max-width: 768px) { 91 .dark-mode-toggle { 92 bottom: 16px; 93 right: 16px; 94 width: 44px; 95 height: 44px; 96 } 97 } 98</style>