forked from zguiy/utils
55 lines
1.3 KiB
TypeScript
55 lines
1.3 KiB
TypeScript
import { ref, watch } from 'vue'
|
|
|
|
type Theme = 'light' | 'dark'
|
|
|
|
// 全局主题状态
|
|
const currentTheme = ref<Theme>('light')
|
|
|
|
export const useTheme = () => {
|
|
// 切换主题
|
|
const toggleTheme = () => {
|
|
currentTheme.value = currentTheme.value === 'light' ? 'dark' : 'light'
|
|
}
|
|
|
|
// 设置主题
|
|
const setTheme = (theme: Theme) => {
|
|
currentTheme.value = theme
|
|
}
|
|
|
|
// 从本地存储恢复主题
|
|
const restoreTheme = () => {
|
|
const saved = localStorage.getItem('preferred-theme') as Theme
|
|
if (saved && (saved === 'light' || saved === 'dark')) {
|
|
currentTheme.value = saved
|
|
} else {
|
|
// 检测系统主题偏好
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
currentTheme.value = prefersDark ? 'dark' : 'light'
|
|
}
|
|
}
|
|
|
|
// 应用主题到DOM
|
|
const applyTheme = (theme: Theme) => {
|
|
const root = document.documentElement
|
|
root.setAttribute('data-theme', theme)
|
|
if (theme === 'dark') {
|
|
root.classList.add('dark')
|
|
} else {
|
|
root.classList.remove('dark')
|
|
}
|
|
}
|
|
|
|
// 监听主题变化
|
|
watch(currentTheme, (newTheme) => {
|
|
applyTheme(newTheme)
|
|
localStorage.setItem('preferred-theme', newTheme)
|
|
}, { immediate: true })
|
|
|
|
return {
|
|
theme: currentTheme,
|
|
toggleTheme,
|
|
setTheme,
|
|
restoreTheme,
|
|
applyTheme
|
|
}
|
|
}
|