mirror of
https://github.com/KazooTTT/kazoottt-blog.git
synced 2025-06-24 11:11:30 +08:00
feat: add theme color sync
This commit is contained in:
@ -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 (
|
||||||
|
@ -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>
|
||||||
|
Reference in New Issue
Block a user