refactor: use `@nuxtjs/color-mode` to manage ssr (#612)
parent
6fdcc558fc
commit
7a36fb8efd
|
@ -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" />
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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 />
|
||||||
|
|
|
@ -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'
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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'
|
|
||||||
}
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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>>
|
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
export default defineNuxtPlugin(() => {
|
||||||
|
const colorMode = useColorMode()
|
||||||
|
useHead({
|
||||||
|
meta: [{
|
||||||
|
id: 'theme-color',
|
||||||
|
name: 'theme-color',
|
||||||
|
content: () => colorMode.value === 'dark' ? '#111111' : '#ffffff',
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
})
|
|
@ -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'),
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
})
|
|
160
pnpm-lock.yaml
160
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue