|
4 | 4 | type Theme = 'dark' | 'light' | 'system'; |
5 | 5 |
|
6 | 6 | let isDark = false; |
7 | | - let open = false; |
8 | 7 | const options: Theme[] = ['light', 'dark', 'system']; |
9 | 8 |
|
10 | 9 | let theme: Theme = 'system'; |
|
39 | 38 | t === 'dark' || (t === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches); |
40 | 39 | if (isDark) document.documentElement.classList.add('dark'); |
41 | 40 | }; |
| 41 | +
|
| 42 | + const changeTheme = () => { |
| 43 | + const currentIndex = options.indexOf(theme); |
| 44 | + const nextIndex = (currentIndex + 1) % options.length; |
| 45 | + applyTheme(options[nextIndex]); |
| 46 | + }; |
42 | 47 | </script> |
43 | 48 |
|
44 | 49 | <div class="relative"> |
45 | 50 | <button |
46 | | - on:click={() => (open = !open)} |
| 51 | + on:click={changeTheme} |
47 | 52 | class="text relative inline-flex h-6 w-6 cursor-pointer justify-between rounded-full pt-1 font-medium text-neutral-700 sm:h-7 sm:w-7 dark:text-white" |
48 | | - aria-label="Theme Mode" |
| 53 | + aria-label="Theme Mode Switch" |
49 | 54 | aria-haspopup="true" |
50 | | - aria-expanded={open ? 'true' : 'false'} |
51 | 55 | > |
52 | 56 | {#if theme === 'dark'} |
53 | 57 | <svg |
|
88 | 92 | </svg> |
89 | 93 | {/if} |
90 | 94 | </button> |
91 | | - |
92 | | - {#if open} |
93 | | - <ul |
94 | | - class="absolute z-10 mt-2 w-32 origin-top-right -translate-x-24 overflow-hidden rounded-md border border-neutral-200 bg-white shadow-lg dark:border-neutral-700 dark:bg-neutral-900" |
95 | | - > |
96 | | - {#each options as option (option)} |
97 | | - <li> |
98 | | - <button |
99 | | - class={'flex w-full cursor-pointer gap-2 px-4 py-2 text-left text-sm capitalize hover:bg-gray-100 dark:hover:bg-neutral-700' + |
100 | | - (option === theme |
101 | | - ? ' text-indigo-500 dark:text-indigo-400' |
102 | | - : ' text-neutral-700 dark:text-neutral-100')} |
103 | | - on:click={() => { |
104 | | - applyTheme(option); |
105 | | - open = false; |
106 | | - }} |
107 | | - aria-label="Select {option} theme" |
108 | | - role="menuitem" |
109 | | - > |
110 | | - {#if option === 'system'} |
111 | | - <svg |
112 | | - xmlns="http://www.w3.org/2000/svg" |
113 | | - viewBox="0 0 20 20" |
114 | | - fill="none" |
115 | | - stroke="currentColor" |
116 | | - stroke-width="2" |
117 | | - stroke-linecap="round" |
118 | | - stroke-linejoin="round" |
119 | | - class="group:hover:text-gray-100 h-5 w-5" |
120 | | - ><rect x="3" y="3" width="14" height="10" rx="2" ry="2"></rect><line |
121 | | - x1="7" |
122 | | - y1="17" |
123 | | - x2="13" |
124 | | - y2="17" |
125 | | - ></line><line x1="10" y1="13" x2="10" y2="17"></line></svg |
126 | | - > |
127 | | - {:else if option === 'light'} |
128 | | - <svg |
129 | | - xmlns="http://www.w3.org/2000/svg" |
130 | | - viewBox="0 0 20 20" |
131 | | - fill="currentColor" |
132 | | - class="group:hover:text-neutral-100 h-5 w-5" |
133 | | - > |
134 | | - <path |
135 | | - fill-rule="evenodd" |
136 | | - d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z" |
137 | | - clip-rule="evenodd" |
138 | | - /> |
139 | | - </svg> |
140 | | - {:else if option === 'dark'} |
141 | | - <svg |
142 | | - xmlns="http://www.w3.org/2000/svg" |
143 | | - viewBox="0 0 20 20" |
144 | | - fill="currentColor" |
145 | | - class="group:hover:text-neutral-100 h-5 w-5" |
146 | | - > |
147 | | - <path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" /> |
148 | | - </svg> |
149 | | - {/if} |
150 | | - {option} |
151 | | - </button> |
152 | | - </li> |
153 | | - {/each} |
154 | | - </ul> |
155 | | - {/if} |
156 | 95 | </div> |
0 commit comments