From 1fb5d228a269e913163246e988806056b3f1b9d9 Mon Sep 17 00:00:00 2001 From: Divyansh Singh <40380293+brc-dd@users.noreply.github.com> Date: Sat, 16 Sep 2023 00:21:15 +0530 Subject: [PATCH] feat(theme): allow forcing dark mode (#2974) --- docs/reference/site-config.md | 2 +- src/client/app/data.ts | 24 ++++++------- .../components/VPNavBarAppearance.vue | 2 +- src/node/config.ts | 35 ++++++++++--------- src/node/siteConfig.ts | 1 + types/shared.d.ts | 1 + 6 files changed, 34 insertions(+), 31 deletions(-) diff --git a/docs/reference/site-config.md b/docs/reference/site-config.md index a0cf9657ddc2..c0fd0adac3c0 100644 --- a/docs/reference/site-config.md +++ b/docs/reference/site-config.md @@ -426,7 +426,7 @@ When set to `true`, the production app will be built in [MPA Mode](../guide/mpa- ### appearance -- Type: `boolean | 'dark' | import('@vueuse/core').UseDarkOptions` +- Type: `boolean | 'dark' | 'force-dark' | import('@vueuse/core').UseDarkOptions` - Default: `true` Whether to enable dark mode (by adding the `.dark` class to the `` element). diff --git a/src/client/app/data.ts b/src/client/app/data.ts index b75f2611cd53..67aa99218689 100644 --- a/src/client/app/data.ts +++ b/src/client/app/data.ts @@ -69,18 +69,18 @@ export function initData(route: Route): VitePressData { resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath) ) - const isDark = site.value.appearance - ? useDark({ - storageKey: APPEARANCE_KEY, - initialValue: () => - typeof site.value.appearance === 'string' - ? site.value.appearance - : 'auto', - ...(typeof site.value.appearance === 'object' - ? site.value.appearance - : {}) - }) - : ref(false) + const appearance = site.value.appearance // fine with reactivity being lost here, config change triggers a restart + const isDark = + appearance === 'force-dark' + ? ref(true) + : appearance + ? useDark({ + storageKey: APPEARANCE_KEY, + initialValue: () => + typeof appearance === 'string' ? appearance : 'auto', + ...(typeof appearance === 'object' ? appearance : {}) + }) + : ref(false) return { site, diff --git a/src/client/theme-default/components/VPNavBarAppearance.vue b/src/client/theme-default/components/VPNavBarAppearance.vue index 9cbe453099a1..b538eb8a1b01 100644 --- a/src/client/theme-default/components/VPNavBarAppearance.vue +++ b/src/client/theme-default/components/VPNavBarAppearance.vue @@ -6,7 +6,7 @@ const { site } = useData() diff --git a/src/node/config.ts b/src/node/config.ts index 0e4ed3961069..b2425c3ecc19 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -255,24 +255,25 @@ function resolveSiteDataHead(userConfig?: UserConfig): HeadConfig[] { ? userConfig.appearance.initialValue ?? 'auto' : 'auto' - head.push( - [ - 'script', - { id: 'check-dark-light' }, - `;(() => { - const preference = localStorage.getItem('${APPEARANCE_KEY}') || '${fallbackPreference}' - const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches - if (!preference || preference === 'auto' ? prefersDark : preference === 'dark') - document.documentElement.classList.add('dark') - })()` - ], - [ - 'script', - { id: 'check-mac-os' }, - `document.documentElement.classList.toggle('mac', /Mac|iPhone|iPod|iPad/i.test(navigator.platform))` - ] - ) + head.push([ + 'script', + { id: 'check-dark-mode' }, + fallbackPreference === 'force-dark' + ? `document.documentElement.classList.add('dark')` + : `;(() => { + const preference = localStorage.getItem('${APPEARANCE_KEY}') || '${fallbackPreference}' + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches + if (!preference || preference === 'auto' ? prefersDark : preference === 'dark') + document.documentElement.classList.add('dark') + })()` + ]) } + head.push([ + 'script', + { id: 'check-mac-os' }, + `document.documentElement.classList.toggle('mac', /Mac|iPhone|iPod|iPad/i.test(navigator.platform))` + ]) + return head } diff --git a/src/node/siteConfig.ts b/src/node/siteConfig.ts index 3005fc7a75ed..d5ec6b83424a 100644 --- a/src/node/siteConfig.ts +++ b/src/node/siteConfig.ts @@ -72,6 +72,7 @@ export interface UserConfig appearance?: | boolean | 'dark' + | 'force-dark' | (Omit & { initialValue?: 'dark' }) lastUpdated?: boolean contentProps?: Record diff --git a/types/shared.d.ts b/types/shared.d.ts index f17d7c4a8d68..5e95cdba1847 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -60,6 +60,7 @@ export interface SiteData { appearance: | boolean | 'dark' + | 'force-dark' | (Omit & { initialValue?: 'dark' }) themeConfig: ThemeConfig scrollOffset: