adding a dark mode toggle for Vue

This commit is contained in:
Brian 2022-05-20 13:52:11 -06:00
parent a14e1b20c0
commit 78bb0f72d5
Signed by: brian
GPG Key ID: DE1A5390A3B84CD8

View File

@ -0,0 +1,81 @@
<script setup>
import { reactive, computed, onBeforeMount, provide } from 'vue'
const emit = defineEmits(['themeUpdate'])
let settings = reactive({
theme: 'light',
})
const htmlNode = document.documentElement
let mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
// computed properties
const isDarkMode = computed(() => {
return settings.theme === 'dark'
})
const isLightMode = computed(() => {
return settings.theme === 'light'
})
// lifecycle hooks
onBeforeMount(() => {
window.addEventListener('storage', update)
if (mediaQuery?.addEventListener) {
mediaQuery.addEventListener('change', update)
}
update()
})
onMounted(() => {
provide('darkMode', isDarkMode)
})
// methods
const update = () => {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
setModeDark()
} else {
setModeLight()
}
emit('themeUpdate')
}
const setModeDark = () => {
settings.theme = 'dark'
localStorage.theme = 'dark'
htmlNode.classList.remove('light')
htmlNode.classList.add('dark')
}
const setModeLight = () => {
settings.theme = 'light'
localStorage.theme = 'light'
htmlNode.classList.remove('dark')
htmlNode.classList.add('light')
}
</script>
<template>
<div class="flex items-center cursor-pointer">
<svg v-show="isDarkMode" @click="setModeLight" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" preserveAspectRatio="xMidYMid meet">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
<svg v-show="isLightMode" @click="setModeDark" viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round" preserveAspectRatio="xMidYMid meet">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path>
</svg>
</div>
</template>