@datametria/vue-components
Version:
DATAMETRIA Vue.js 3 Component Library with Multi-Brand Theming - 51 components + 10 composables with theming support, WCAG 2.2 AA, dark mode, responsive system
67 lines (55 loc) • 1.75 kB
text/typescript
import { ref, computed } from 'vue'
let isDark = ref(false)
let initialized = false
// Reset function for testing
export function resetTheme() {
isDark = ref(false)
initialized = false
document.documentElement.classList.remove('dark')
}
export function useTheme() {
const toggleTheme = () => {
isDark.value = !isDark.value
document.documentElement.classList.toggle('dark', isDark.value)
localStorage.setItem('theme', isDark.value ? 'dark' : 'light')
}
const setTheme = (theme: 'light' | 'dark') => {
isDark.value = theme === 'dark'
document.documentElement.classList.toggle('dark', isDark.value)
localStorage.setItem('theme', theme)
}
const initTheme = () => {
initialized = true
const savedTheme = localStorage.getItem('theme')
if (savedTheme) {
setTheme(savedTheme as 'light' | 'dark')
} else if (typeof window !== 'undefined' && window.matchMedia) {
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches
setTheme(prefersDark ? 'dark' : 'light')
}
// Listen for system preference changes
if (typeof window !== 'undefined' && window.matchMedia) {
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!localStorage.getItem('theme')) {
setTheme(e.matches ? 'dark' : 'light')
}
})
}
}
// Auto-initialize on first use
if (!initialized) {
initTheme()
}
const currentTheme = computed(() => isDark.value ? 'dark' : 'light')
const setDark = () => setTheme('dark')
const setLight = () => setTheme('light')
return {
isDark,
currentTheme,
toggle: toggleTheme,
setTheme,
setDark,
setLight,
initTheme
}
}