更新
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
import { computed, ref } from 'vue'
|
||||
|
||||
const STORAGE_KEY = 'ai-chat-theme'
|
||||
const DEFAULT_THEME = 'light'
|
||||
|
||||
function readStoredTheme() {
|
||||
try {
|
||||
return localStorage.getItem(STORAGE_KEY) === 'dark' ? 'dark' : DEFAULT_THEME
|
||||
} catch {
|
||||
return DEFAULT_THEME
|
||||
}
|
||||
}
|
||||
|
||||
const theme = ref(readStoredTheme())
|
||||
let transitionTimer
|
||||
|
||||
function applyTheme(value, animate = false) {
|
||||
const nextTheme = value === 'dark' ? 'dark' : 'light'
|
||||
const root = document.documentElement
|
||||
|
||||
if (animate) {
|
||||
root.classList.add('theme-transitioning')
|
||||
window.clearTimeout(transitionTimer)
|
||||
transitionTimer = window.setTimeout(() => root.classList.remove('theme-transitioning'), 260)
|
||||
}
|
||||
|
||||
root.dataset.theme = nextTheme
|
||||
root.style.colorScheme = nextTheme
|
||||
theme.value = nextTheme
|
||||
}
|
||||
|
||||
export function initializeTheme() {
|
||||
applyTheme(theme.value)
|
||||
}
|
||||
|
||||
export function useTheme() {
|
||||
const isDark = computed(() => theme.value === 'dark')
|
||||
|
||||
function setTheme(value) {
|
||||
const nextTheme = value === 'dark' ? 'dark' : 'light'
|
||||
applyTheme(nextTheme, true)
|
||||
try {
|
||||
localStorage.setItem(STORAGE_KEY, nextTheme)
|
||||
} catch {
|
||||
// Theme still works for the current session when storage is unavailable.
|
||||
}
|
||||
}
|
||||
|
||||
return { theme, isDark, setTheme }
|
||||
}
|
||||
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('storage', event => {
|
||||
if (event.key === STORAGE_KEY) applyTheme(event.newValue)
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user