61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
/** Pinia store for theme management */
|
|
import { defineStore } from 'pinia'
|
|
import { ref } from 'vue'
|
|
|
|
export const useThemeStore = defineStore('theme', () => {
|
|
// Check localStorage first, then system preference
|
|
const getInitialTheme = (): boolean => {
|
|
const stored = localStorage.getItem('darkMode')
|
|
if (stored !== null) {
|
|
return stored === 'true'
|
|
}
|
|
// Check system preference
|
|
return window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
}
|
|
|
|
const isDarkMode = ref<boolean>(getInitialTheme())
|
|
|
|
// Apply theme to document
|
|
function applyTheme() {
|
|
if (isDarkMode.value) {
|
|
document.documentElement.classList.add('dark')
|
|
document.documentElement.classList.remove('light-theme')
|
|
} else {
|
|
document.documentElement.classList.remove('dark')
|
|
document.documentElement.classList.add('light-theme')
|
|
}
|
|
localStorage.setItem('darkMode', String(isDarkMode.value))
|
|
}
|
|
|
|
function toggleDarkMode() {
|
|
isDarkMode.value = !isDarkMode.value
|
|
applyTheme()
|
|
}
|
|
|
|
function setDarkMode(value: boolean) {
|
|
isDarkMode.value = value
|
|
applyTheme()
|
|
}
|
|
|
|
// Watch for system theme changes
|
|
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
|
|
const handleSystemThemeChange = (e: MediaQueryListEvent) => {
|
|
if (!localStorage.getItem('darkMode')) {
|
|
isDarkMode.value = e.matches
|
|
applyTheme()
|
|
}
|
|
}
|
|
mediaQuery.addEventListener('change', handleSystemThemeChange)
|
|
|
|
// Apply theme on initialization
|
|
applyTheme()
|
|
|
|
return {
|
|
isDarkMode,
|
|
toggleDarkMode,
|
|
setDarkMode,
|
|
applyTheme,
|
|
}
|
|
})
|
|
|