feat: add theme color sync

This commit is contained in:
KazooTTT
2024-11-23 22:13:37 +08:00
parent ebcc468e7e
commit 693b063489
2 changed files with 65 additions and 21 deletions

View File

@ -9,10 +9,33 @@ const GiscusComment = () => {
const [theme, setTheme] = React.useState('preferred_color_scheme') const [theme, setTheme] = React.useState('preferred_color_scheme')
React.useEffect(() => { React.useEffect(() => {
// Initial theme setup
const savedTheme = localStorage.getItem('theme') const savedTheme = localStorage.getItem('theme')
if (savedTheme) { if (savedTheme) {
setTheme(savedTheme) setTheme(savedTheme)
} }
// Listen for theme changes
const handleThemeChange = (e: CustomEvent<{ theme: string }>) => {
setTheme(e.detail.theme)
}
document.addEventListener('theme-change', handleThemeChange as EventListener)
// Listen for astro:after-swap events (view transitions)
const handleAfterSwap = () => {
const currentTheme = localStorage.getItem('theme')
if (currentTheme) {
setTheme(currentTheme)
}
}
document.addEventListener('astro:after-swap', handleAfterSwap)
return () => {
document.removeEventListener('theme-change', handleThemeChange as EventListener)
document.removeEventListener('astro:after-swap', handleAfterSwap)
}
}, []) }, [])
return ( return (

View File

@ -3,9 +3,9 @@ import kazootttAvatar from '../../assets/kazoottt-avatar.jpeg'
import { Image } from 'astro:assets' import { Image } from 'astro:assets'
--- ---
<header class='fixed top-0 left-0 right-0 z-50 bg-white dark:bg-gray-800 shadow-sm'> <header class='fixed left-0 right-0 top-0 z-50 bg-white shadow-sm dark:bg-gray-800'>
<nav <nav
class='mx-auto flex w-full items-center justify-between px-4 py-3 sm:flex sm:items-center' class='mx-auto flex w-full items-center justify-between px-4 py-3 sm:flex sm:w-3/5 sm:items-center'
aria-label='global' aria-label='global'
> >
<a class='flex items-center' href='/'> <a class='flex items-center' href='/'>
@ -192,28 +192,49 @@ import { Image } from 'astro:assets'
function getCurrentTheme() { function getCurrentTheme() {
return localStorage.getItem('theme') return localStorage.getItem('theme')
} }
function setupDarkModeToggle() {
const toggleDarkModeButton = document.getElementById('toggleDarkMode') const toggleDarkModeButton = document.getElementById('toggleDarkMode')
if (!toggleDarkModeButton) return
toggleDarkModeButton.addEventListener('click', () => {
const currentTheme = getCurrentTheme()
const newTheme = currentTheme === 'dark' ? 'light' : 'dark'
localStorage.setItem('theme', newTheme)
document.documentElement.classList.toggle('dark')
// Dispatch theme change event
window.dispatchEvent(new CustomEvent('theme-change', { detail: { theme: newTheme } }))
})
}
function setupMobileMenu() {
const mobileMenuButton = document.getElementById('mobileMenuButton') const mobileMenuButton = document.getElementById('mobileMenuButton')
const mobileMenu = document.getElementById('mobileMenu') const mobileMenu = document.getElementById('mobileMenu')
if (!mobileMenuButton || !mobileMenu) return
toggleDarkModeButton?.addEventListener('click', () => { mobileMenuButton.addEventListener('click', () => {
const toggleDarkModeEvent = new CustomEvent('theme-change', { mobileMenu.classList.toggle('hidden')
detail: { theme: getCurrentTheme() === 'light' ? 'dark' : 'light' }
})
document.dispatchEvent(toggleDarkModeEvent)
})
mobileMenuButton?.addEventListener('click', () => {
mobileMenu?.classList.toggle('hidden')
}) })
// Close mobile menu when clicking outside // Close mobile menu when clicking outside
document.addEventListener('click', (event) => { document.addEventListener('click', (event) => {
if ( if (
!mobileMenuButton?.contains(event.target as Node) && !mobileMenuButton.contains(event.target as Node) &&
!mobileMenu?.contains(event.target as Node) !mobileMenu.contains(event.target as Node)
) { ) {
mobileMenu?.classList.add('hidden') mobileMenu.classList.add('hidden')
} }
}) })
}
// Setup initial functionality
setupDarkModeToggle()
setupMobileMenu()
// Re-setup functionality after view transitions
document.addEventListener('astro:after-swap', () => {
setupDarkModeToggle()
setupMobileMenu()
})
</script> </script>