blog.z0x.ca/src/components/ThemeToggle.astro
z0x 17a1981fba
All checks were successful
build dist / build-dist (push) Successful in 47s
feat: update theme handling and improve icons
2025-05-23 21:04:11 -04:00

92 lines
No EOL
2.5 KiB
Text

---
import { Button } from "@/components/ui/button";
import { Icon } from "astro-icon/components";
---
<Button
id="theme-toggle"
variant="ghost"
size="icon"
title="Toggle theme"
className="-me-2 size-8"
>
<Icon
name="lucide:sun"
class="size-4 scale-100 rotate-0 transition-all dark:scale-0 dark:-rotate-90"
/>
<Icon
name="lucide:moon"
class="absolute size-4 scale-0 rotate-90 transition-all dark:scale-100 dark:rotate-0"
/>
<span class="sr-only">Toggle theme</span>
</Button>
<script is:inline data-astro-rerun>
const theme = (() => {
const localStorageTheme = localStorage?.getItem('theme') ?? ''
if (['dark', 'light'].includes(localStorageTheme)) {
return localStorageTheme
}
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
return 'dark'
}
return 'light'
})()
document.documentElement.setAttribute('data-theme', theme)
document.documentElement.classList.add(
theme === 'dark' ? 'scheme-dark' : 'scheme-light',
)
window.localStorage.setItem('theme', theme)
</script>
<script>
function handleToggleClick() {
const element = document.documentElement
const currentTheme = element.getAttribute('data-theme')
const newTheme = currentTheme === 'dark' ? 'light' : 'dark'
element.classList.add('[&_*]:transition-none')
element.setAttribute('data-theme', newTheme)
element.classList.remove('scheme-dark', 'scheme-light')
element.classList.add(newTheme === 'dark' ? 'scheme-dark' : 'scheme-light')
window.getComputedStyle(element).getPropertyValue('opacity')
requestAnimationFrame(() => {
element.classList.remove('[&_*]:transition-none')
})
localStorage.setItem('theme', newTheme)
}
function initThemeToggle() {
const themeToggle = document.getElementById('theme-toggle')
if (themeToggle) {
themeToggle.addEventListener('click', handleToggleClick)
}
}
initThemeToggle()
document.addEventListener('astro:after-swap', () => {
const storedTheme = localStorage.getItem('theme') || 'light'
const element = document.documentElement
element.classList.add('[&_*]:transition-none')
window.getComputedStyle(element).getPropertyValue('opacity')
element.setAttribute('data-theme', storedTheme)
element.classList.remove('scheme-dark', 'scheme-light')
element.classList.add(
storedTheme === 'dark' ? 'scheme-dark' : 'scheme-light',
)
requestAnimationFrame(() => {
element.classList.remove('[&_*]:transition-none')
})
initThemeToggle()
})
</script>