refactor: use @nuxtjs/color-mode to manage ssr (#612)

This commit is contained in:
Daniel Roe 2022-12-29 13:26:08 +01:00 committed by GitHub
parent 6fdcc558fc
commit 7a36fb8efd
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 43 additions and 215 deletions

View file

@ -5,7 +5,7 @@ defineProps<{
}>() }>()
const dropdown = $ref<any>() const dropdown = $ref<any>()
const colorMode = useColorModeRef() const colorMode = useColorMode()
provide(dropdownContextKey, { provide(dropdownContextKey, {
hide: () => dropdown.hide(), hide: () => dropdown.hide(),
@ -13,7 +13,7 @@ provide(dropdownContextKey, {
</script> </script>
<template> <template>
<VDropdown v-bind="$attrs" ref="dropdown" :class="colorMode" :placement="placement || 'auto'"> <VDropdown v-bind="$attrs" ref="dropdown" :class="colorMode.value" :placement="placement || 'auto'">
<slot /> <slot />
<template #popper="scope"> <template #popper="scope">
<slot name="popper" v-bind="scope" /> <slot name="popper" v-bind="scope" />

View file

@ -6,7 +6,7 @@ const emits = defineEmits<{
(event: 'update:modelValue', value: boolean): void (event: 'update:modelValue', value: boolean): void
}>() }>()
const visible = useVModel(props, 'modelValue', emits, { passive: true }) const visible = useVModel(props, 'modelValue', emits, { passive: true })
const colorMode = useColorModeRef() const colorMode = useColorMode()
function changeShow() { function changeShow() {
visible.value = !visible.value visible.value = !visible.value
@ -24,7 +24,7 @@ function clickEvent(mouse: MouseEvent) {
} }
function toggleDark() { function toggleDark() {
colorMode.value = colorMode.value === 'dark' ? 'light' : 'dark' colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
} }
watch(visible, (val) => { watch(visible, (val) => {
@ -84,7 +84,7 @@ onBeforeUnmount(() => {
@click="toggleDark()" @click="toggleDark()"
> >
<span class="i-ri:sun-line dark:i-ri:moon-line flex-shrink-0 text-xl mr-4 rtl-mr-0 rtl-ml-4 !align-middle" /> <span class="i-ri:sun-line dark:i-ri:moon-line flex-shrink-0 text-xl mr-4 rtl-mr-0 rtl-ml-4 !align-middle" />
{{ colorMode === 'light' ? $t('menu.toggle_theme.dark') : $t('menu.toggle_theme.light') }} {{ colorMode.value === 'light' ? $t('menu.toggle_theme.dark') : $t('menu.toggle_theme.light') }}
</button> </button>
<NuxtLink <NuxtLink
flex flex-row items-center flex flex-row items-center

View file

@ -6,9 +6,9 @@ const timeAgoOptions = useTimeAgoOptions()
const buildTimeDate = new Date(buildInfo.time) const buildTimeDate = new Date(buildInfo.time)
const buildTimeAgo = useTimeAgo(buildTimeDate, timeAgoOptions) const buildTimeAgo = useTimeAgo(buildTimeDate, timeAgoOptions)
const colorMode = useColorModeRef() const colorMode = useColorMode()
function toggleDark() { function toggleDark() {
colorMode.value = colorMode.value === 'dark' ? 'light' : 'dark' colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
} }
</script> </script>

View file

@ -8,7 +8,7 @@ const emit = defineEmits<{
const el = $ref<HTMLElement>() const el = $ref<HTMLElement>()
let picker = $ref<Picker>() let picker = $ref<Picker>()
const colorMode = useColorModeRef() const colorMode = useColorMode()
async function openEmojiPicker() { async function openEmojiPicker() {
await updateCustomEmojis() await updateCustomEmojis()

View file

@ -1,10 +1,10 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColorMode } from '~/types' import type { ColorMode } from '~/types'
const colorMode = useColorModeRef() const colorMode = useColorMode()
function setColorMode(mode: ColorMode) { function setColorMode(mode: ColorMode) {
colorMode.value = mode colorMode.preference = mode
} }
</script> </script>
@ -12,7 +12,7 @@ function setColorMode(mode: ColorMode) {
<div flex="~ gap4" w-full> <div flex="~ gap4" w-full>
<button <button
btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base
:class="colorMode === 'dark' ? 'pointer-events-none' : 'filter-saturate-0'" :class="colorMode.value === 'dark' ? 'pointer-events-none' : 'filter-saturate-0'"
@click="setColorMode('dark')" @click="setColorMode('dark')"
> >
<div i-ri:moon-line /> <div i-ri:moon-line />
@ -20,7 +20,7 @@ function setColorMode(mode: ColorMode) {
</button> </button>
<button <button
btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base btn-text flex-1 flex="~ gap-1 center" p4 border="~ base rounded" bg-base
:class="colorMode === 'light' ? 'pointer-events-none' : 'filter-saturate-0'" :class="colorMode.value === 'light' ? 'pointer-events-none' : 'filter-saturate-0'"
@click="setColorMode('light')" @click="setColorMode('light')"
> >
<div i-ri:sun-line /> <div i-ri:sun-line />

View file

@ -241,7 +241,7 @@ export const provideGlobalCommands = () => {
const { locales } = useI18n() as { locales: ComputedRef<LocaleObject[]> } const { locales } = useI18n() as { locales: ComputedRef<LocaleObject[]> }
const users = useUsers() const users = useUsers()
const masto = useMasto() const masto = useMasto()
const colorMode = useColorModeRef() const colorMode = useColorMode()
useCommand({ useCommand({
scope: 'Actions', scope: 'Actions',
@ -264,7 +264,7 @@ export const provideGlobalCommands = () => {
icon: () => colorMode.value === 'light' ? 'i-ri:sun-line' : 'i-ri:moon-line', icon: () => colorMode.value === 'light' ? 'i-ri:sun-line' : 'i-ri:moon-line',
onActivate() { onActivate() {
colorMode.value = colorMode.value === 'light' ? 'dark' : 'light' colorMode.preference = colorMode.value === 'light' ? 'dark' : 'light'
}, },
}) })

View file

@ -1,14 +1,5 @@
import { InjectionKeyColorMode, InjectionKeyFontSize } from '~/constants/symbols' import { InjectionKeyFontSize } from '~/constants/symbols'
export function useFontSizeRef() { export function useFontSizeRef() {
return inject(InjectionKeyFontSize)! return inject(InjectionKeyFontSize)!
} }
export function useColorModeRef() {
return inject(InjectionKeyColorMode)!
}
export function toggleColorMode() {
const colorMode = useColorModeRef()
colorMode.value = colorMode.value === 'light' ? 'dark' : 'light'
}

View file

@ -44,7 +44,7 @@ export function useHightlighter(lang: Lang) {
} }
export function useShikiTheme() { export function useShikiTheme() {
return useColorModeRef().value ? 'vitesse-dark' : 'vitesse-light' return useColorMode().value === 'dark' ? 'vitesse-dark' : 'vitesse-light'
} }
export function highlightCode(code: string, lang: Lang) { export function highlightCode(code: string, lang: Lang) {

View file

@ -1,5 +1,4 @@
import type { InjectionKey, Ref } from 'vue' import type { InjectionKey, Ref } from 'vue'
import type { ColorMode, FontSize } from '~/types' import type { FontSize } from '~/types'
export const InjectionKeyFontSize = Symbol('font-size') as InjectionKey<Ref<FontSize>> export const InjectionKeyFontSize = Symbol('font-size') as InjectionKey<Ref<FontSize>>
export const InjectionKeyColorMode = Symbol('color-mode') as InjectionKey<Ref<ColorMode>>

View file

@ -19,6 +19,7 @@ export default defineNuxtConfig({
'@pinia/nuxt', '@pinia/nuxt',
'@vue-macros/nuxt', '@vue-macros/nuxt',
'@nuxtjs/i18n', '@nuxtjs/i18n',
'@nuxtjs/color-mode',
'~/modules/purge-comments', '~/modules/purge-comments',
'~/modules/setup-components', '~/modules/setup-components',
'~/modules/build-info', '~/modules/build-info',
@ -130,6 +131,7 @@ export default defineNuxtConfig({
], ],
}, },
}, },
colorMode: { classSuffix: '' },
i18n, i18n,
pwa, pwa,
}) })

View file

@ -26,6 +26,7 @@
}, },
"dependencies": { "dependencies": {
"@fnando/sparkline": "^0.3.10", "@fnando/sparkline": "^0.3.10",
"@nuxtjs/color-mode": "^3.2.0",
"@tiptap/extension-character-count": "2.0.0-beta.204", "@tiptap/extension-character-count": "2.0.0-beta.204",
"@tiptap/extension-code-block": "2.0.0-beta.204", "@tiptap/extension-code-block": "2.0.0-beta.204",
"@tiptap/extension-mention": "2.0.0-beta.204", "@tiptap/extension-mention": "2.0.0-beta.204",

10
plugins/color-mode.ts Normal file
View file

@ -0,0 +1,10 @@
export default defineNuxtPlugin(() => {
const colorMode = useColorMode()
useHead({
meta: [{
id: 'theme-color',
name: 'theme-color',
content: () => colorMode.value === 'dark' ? '#111111' : '#ffffff',
}],
})
})

View file

@ -1,41 +0,0 @@
import type { ColorMode } from '~/types'
import { InjectionKeyColorMode } from '~/constants/symbols'
import { COOKIE_KEY_COLOR_MODE, COOKIE_MAX_AGE } from '~/constants'
export default defineNuxtPlugin((nuxt) => {
const cookieColorMode = useCookie<ColorMode | null>(COOKIE_KEY_COLOR_MODE, { maxAge: COOKIE_MAX_AGE })
const preferColorMode = process.server ? computed(() => 'light') : usePreferredColorScheme()
const colorMode = computed<ColorMode>({
get() {
return cookieColorMode.value || preferColorMode.value as ColorMode
},
set(value) {
cookieColorMode.value = value
},
})
nuxt.vueApp.provide(InjectionKeyColorMode, colorMode)
if (process.server) {
useHead({
htmlAttrs: {
class: colorMode,
},
})
}
else {
watchEffect(() => {
document.documentElement.classList.toggle('dark', colorMode.value === 'dark')
document.documentElement.classList.toggle('light', colorMode.value === 'light')
})
}
useHead({
meta: [{
id: 'theme-color',
name: 'theme-color',
content: computed(() => colorMode.value === 'dark' ? '#111111' : '#ffffff'),
}],
})
})

File diff suppressed because it is too large Load diff