Files
chat/frontend/src/composables/useTheme.js
T
2026-08-03 10:00:05 +08:00

57 lines
1.4 KiB
JavaScript

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)
})
}