ModeToggle.jsx

 1function SunIcon(props) {
 2  return (
 3    <svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
 4      <path d="M12.5 10a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0Z" />
 5      <path
 6        strokeLinecap="round"
 7        d="M10 5.5v-1M13.182 6.818l.707-.707M14.5 10h1M13.182 13.182l.707.707M10 15.5v-1M6.11 13.889l.708-.707M4.5 10h1M6.11 6.111l.708.707"
 8      />
 9    </svg>
10  )
11}
12
13function MoonIcon(props) {
14  return (
15    <svg viewBox="0 0 20 20" fill="none" aria-hidden="true" {...props}>
16      <path d="M15.224 11.724a5.5 5.5 0 0 1-6.949-6.949 5.5 5.5 0 1 0 6.949 6.949Z" />
17    </svg>
18  )
19}
20
21export function ModeToggle() {
22  function disableTransitionsTemporarily() {
23    document.documentElement.classList.add('[&_*]:!transition-none')
24    window.setTimeout(() => {
25      document.documentElement.classList.remove('[&_*]:!transition-none')
26    }, 0)
27  }
28
29  function toggleMode() {
30    disableTransitionsTemporarily()
31
32    let darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
33    let isSystemDarkMode = darkModeMediaQuery.matches
34    let isDarkMode = document.documentElement.classList.toggle('dark')
35
36    if (isDarkMode === isSystemDarkMode) {
37      delete window.localStorage.isDarkMode
38    } else {
39      window.localStorage.isDarkMode = isDarkMode
40    }
41  }
42
43  return (
44    <button
45      type="button"
46      className="flex h-6 w-6 items-center justify-center rounded-md transition hover:bg-zinc-900/5 dark:hover:bg-white/5"
47      aria-label="Toggle dark mode"
48      onClick={toggleMode}
49    >
50      <SunIcon className="h-5 w-5 stroke-zinc-900 dark:hidden" />
51      <MoonIcon className="hidden h-5 w-5 stroke-white dark:block" />
52    </button>
53  )
54}