portfolio/src/stores/theme-store.ts

56 lines
1.3 KiB
TypeScript

import { create } from 'zustand'
import { persist } from 'zustand/middleware'
import { config } from '@lib/config'
import type { Theme } from '@lib/config'
interface ThemeState {
theme: Theme
setTheme: (theme: Theme) => void
}
const getSystemTheme = (): 'light' | 'dark' => {
if (typeof window === 'undefined') return 'light'
return window.matchMedia('(prefers-color-scheme: dark)').matches
? 'dark'
: 'light'
}
const applyTheme = (theme: Theme) => {
const root = document.documentElement
const resolvedTheme = theme === 'system' ? getSystemTheme() : theme
root.classList.remove('light', 'dark')
root.classList.add(resolvedTheme)
}
export const useThemeStore = create<ThemeState>()(
persist(
(set) => ({
theme: config.defaultTheme,
setTheme: (theme) => {
applyTheme(theme)
set({ theme })
},
}),
{
name: 'theme-storage',
onRehydrateStorage: () => (state) => {
if (state) {
applyTheme(state.theme)
}
},
},
),
)
if (typeof window !== 'undefined') {
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', () => {
const { theme } = useThemeStore.getState()
if (theme === 'system') {
applyTheme('system')
}
})
}