web-app/src/components/theme-provider/index.ts

61 lines
No EOL
1.5 KiB
TypeScript

import { computed, onMounted, ref, watch } from 'vue'
type Theme = 'dark' | 'light' | 'system'
const useTheme = () => {
const theme = ref<Theme>('dark')
const systemTheme = ref<'dark' | 'light'>('light')
const currentTown = ref(localStorage.getItem('current-town') || 'all')
const updateSystemTheme = () => {
systemTheme.value = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
const currentTheme = computed(() => {
return theme.value === 'system' ? systemTheme.value : theme.value
})
const applyTheme = () => {
if (currentTheme.value === 'dark') {
document.documentElement.classList.add('dark')
} else {
document.documentElement.classList.remove('dark')
}
}
onMounted(() => {
const stored = localStorage.getItem('ui-theme')
if (stored && (stored === 'dark' || stored === 'light' || stored === 'system')) {
theme.value = stored as Theme
}
updateSystemTheme()
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', updateSystemTheme)
applyTheme()
})
watch(currentTheme, () => {
applyTheme()
})
const setTheme = (newTheme: Theme) => {
theme.value = newTheme
localStorage.setItem('ui-theme', newTheme)
}
const setCurrentTown = (town: string) => {
currentTown.value = town
localStorage.setItem('current-town', town)
}
return {
theme,
setTheme,
systemTheme,
currentTheme,
currentTown,
setCurrentTown
}
}
export { useTheme }