From 46b6ae53bb989c0137145bf8d47bdb5e2331fc54 Mon Sep 17 00:00:00 2001 From: Zenith Rifle <84105075+eli32-vlc@users.noreply.github.com> Date: Sun, 4 Jan 2026 21:32:51 +0800 Subject: [PATCH] Add monochrome theme with grayscale filter (#4541) --- .../theme/components/ColorPicker.vue | 4 - docs/.vitepress/theme/style.scss | 28 ++-- docs/.vitepress/theme/themes/configs/index.ts | 4 +- .../theme/themes/configs/monochrome.ts | 151 ++++++++++++++++++ docs/.vitepress/theme/themes/themeHandler.ts | 38 ++--- 5 files changed, 186 insertions(+), 39 deletions(-) create mode 100644 docs/.vitepress/theme/themes/configs/monochrome.ts diff --git a/docs/.vitepress/theme/components/ColorPicker.vue b/docs/.vitepress/theme/components/ColorPicker.vue index 607043b75..8cf98c059 100644 --- a/docs/.vitepress/theme/components/ColorPicker.vue +++ b/docs/.vitepress/theme/components/ColorPicker.vue @@ -211,12 +211,8 @@ watch(selectedColor, async (color) => { if (!color) return; const theme = generateThemeFromColor(color) themeRegistry[`color-${color}`] = theme - // Explicitly set the theme to override any previous selection await nextTick() - console.log('Setting theme to:', `color-${color}`) - console.log('Current themeName:', themeName ? themeName.value : undefined, 'mode:', mode ? (mode as any).value : undefined) setTheme(`color-${color}`) - console.log('After setTheme, themeName:', themeName ? themeName.value : undefined) }) const toggleAmoled = () => { diff --git a/docs/.vitepress/theme/style.scss b/docs/.vitepress/theme/style.scss index 6c1b54432..8dac12032 100644 --- a/docs/.vitepress/theme/style.scss +++ b/docs/.vitepress/theme/style.scss @@ -81,6 +81,15 @@ --vp-custom-block-danger-text-deep: theme('colors.carnation.200'); } +.monochrome { + + [class*='i-'], + svg, + img:not(.VPImage) { + filter: grayscale(100%); + } +} + .vp-doc a { color: var(--vp-c-brand-1); text-decoration: underline; @@ -138,17 +147,13 @@ */ :root { --vp-home-hero-name-color: transparent; - --vp-home-hero-name-background: -webkit-linear-gradient( - 120deg, - #c4b5fd 30%, - #7bc5e4 - ); + --vp-home-hero-name-background: -webkit-linear-gradient(120deg, + #c4b5fd 30%, + #7bc5e4); - --vp-home-hero-image-background-image: linear-gradient( - -45deg, - #c4b5fd 50%, - #47caff 50% - ); + --vp-home-hero-image-background-image: linear-gradient(-45deg, + #c4b5fd 50%, + #47caff 50%); --vp-home-hero-image-filter: blur(44px); } @@ -223,6 +228,7 @@ animation: nprogress-spinner 400ms linear infinite; } } + .nprogress-custom-parent { overflow: hidden; position: relative; @@ -253,7 +259,7 @@ } } -#VPContent strong > a { +#VPContent strong>a { font-weight: bold; } diff --git a/docs/.vitepress/theme/themes/configs/index.ts b/docs/.vitepress/theme/themes/configs/index.ts index b8f90fec3..c0e67b5e4 100644 --- a/docs/.vitepress/theme/themes/configs/index.ts +++ b/docs/.vitepress/theme/themes/configs/index.ts @@ -14,10 +14,12 @@ * limitations under the License. */ import { catppuccinTheme } from './catppuccin' +import { monochromeTheme } from './monochrome' import type { ThemeRegistry } from '../types' export const themeRegistry: ThemeRegistry = { catppuccin: catppuccinTheme, + monochrome: monochromeTheme, } -export { catppuccinTheme } +export { catppuccinTheme, monochromeTheme } diff --git a/docs/.vitepress/theme/themes/configs/monochrome.ts b/docs/.vitepress/theme/themes/configs/monochrome.ts new file mode 100644 index 000000000..b9659d78d --- /dev/null +++ b/docs/.vitepress/theme/themes/configs/monochrome.ts @@ -0,0 +1,151 @@ +import type { Theme } from '../types' + +export const monochromeTheme: Theme = { + name: 'monochrome', + displayName: 'Monochrome', + preview: '#808080', + modes: { + light: { + brand: { + 1: '#000000', + 2: '#1a1a1a', + 3: '#333333', + soft: '#666666' + }, + bg: '#FFFFFF', + bgAlt: '#F5F5F5', + bgElv: 'rgba(255, 255, 255, 0.95)', + bgMark: '#E0E0E0', + text: { + 1: '#000000', + 2: '#333333', + 3: '#808080' + }, + button: { + brand: { + bg: '#000000', + border: '#000000', + text: '#FFFFFF', + hoverBorder: '#333333', + hoverText: '#FFFFFF', + hoverBg: '#333333', + activeBorder: '#000000', + activeText: '#FFFFFF', + activeBg: '#000000' + }, + alt: { + bg: '#808080', + text: '#FFFFFF', + hoverBg: '#666666', + hoverText: '#FFFFFF' + } + }, + customBlock: { + info: { + bg: '#F5F5F5', + border: '#000000', + text: '#000000', + textDeep: '#000000' + }, + tip: { + bg: '#F5F5F5', + border: '#333333', + text: '#1a1a1a', + textDeep: '#000000' + }, + warning: { + bg: '#F5F5F5', + border: '#666666', + text: '#333333', + textDeep: '#1a1a1a' + }, + danger: { + bg: '#F5F5F5', + border: '#000000', + text: '#000000', + textDeep: '#000000' + } + }, + selection: { + bg: '#CCCCCC' + }, + home: { + heroNameColor: '#000000', + heroNameBackground: '#FFFFFF', + heroImageBackground: 'linear-gradient(135deg, #E0E0E0 0%, #FFFFFF 100%)', + heroImageFilter: 'blur(44px)' + } + }, + dark: { + brand: { + 1: '#FFFFFF', + 2: '#E0E0E0', + 3: '#CCCCCC', + soft: '#999999' + }, + bg: '#000000', + bgAlt: '#0A0A0A', + bgElv: 'rgba(0, 0, 0, 0.95)', + bgMark: '#1A1A1A', + text: { + 1: '#FFFFFF', + 2: '#CCCCCC', + 3: '#808080' + }, + button: { + brand: { + bg: '#FFFFFF', + border: '#FFFFFF', + text: '#000000', + hoverBorder: '#CCCCCC', + hoverText: '#000000', + hoverBg: '#CCCCCC', + activeBorder: '#FFFFFF', + activeText: '#000000', + activeBg: '#FFFFFF' + }, + alt: { + bg: '#808080', + text: '#000000', + hoverBg: '#999999', + hoverText: '#000000' + } + }, + customBlock: { + info: { + bg: '#1A1A1A', + border: '#FFFFFF', + text: '#FFFFFF', + textDeep: '#FFFFFF' + }, + tip: { + bg: '#1A1A1A', + border: '#CCCCCC', + text: '#E0E0E0', + textDeep: '#FFFFFF' + }, + warning: { + bg: '#1A1A1A', + border: '#999999', + text: '#CCCCCC', + textDeep: '#E0E0E0' + }, + danger: { + bg: '#1A1A1A', + border: '#FFFFFF', + text: '#FFFFFF', + textDeep: '#FFFFFF' + } + }, + selection: { + bg: '#333333' + }, + home: { + heroNameColor: '#FFFFFF', + heroNameBackground: '#000000', + heroImageBackground: 'linear-gradient(135deg, #1A1A1A 0%, #000000 100%)', + heroImageFilter: 'blur(44px)' + } + } + } +} diff --git a/docs/.vitepress/theme/themes/themeHandler.ts b/docs/.vitepress/theme/themes/themeHandler.ts index 9016cec48..c11c1601d 100644 --- a/docs/.vitepress/theme/themes/themeHandler.ts +++ b/docs/.vitepress/theme/themes/themeHandler.ts @@ -66,8 +66,8 @@ export class ThemeHandler { if (!localStorage.getItem(STORAGE_KEY_MODE)) { this.state.value.currentMode = e.matches ? 'dark' : 'light' this.applyTheme() - } - else { + } + else { this.applyTheme() } }) @@ -95,17 +95,23 @@ export class ThemeHandler { this.applyDOMClasses(currentMode) this.applyCSSVariables(modeColors, theme) + + if (theme.name === 'monochrome') { + root.classList.add('monochrome') + } else { + root.classList.remove('monochrome') + } } private applyDOMClasses(mode: DisplayMode) { const root = document.documentElement - + // Remove all mode classes root.classList.remove('dark', 'light', 'amoled') - + // Add current mode class root.classList.add(mode) - + // Add amoled class if enabled in dark mode if (mode === 'dark' && this.amoledEnabled.value) { root.classList.add('amoled') @@ -127,7 +133,7 @@ export class ThemeHandler { let bgColor = colors.bg let bgAltColor = colors.bgAlt let bgElvColor = colors.bgElv - + if (this.state.value.currentMode === 'dark' && this.amoledEnabled.value) { bgColor = '#000000' bgAltColor = '#000000' @@ -170,20 +176,6 @@ export class ThemeHandler { root.style.removeProperty('--vp-c-text-3') } - // Debug: log applied text color variables so we can inspect in console - try { - // eslint-disable-next-line no-console - console.log('[ThemeHandler] applied text vars', { - theme: theme.name, - mode: this.state.value.currentMode, - vp_text_1: root.style.getPropertyValue('--vp-c-text-1'), - vp_text_2: root.style.getPropertyValue('--vp-c-text-2'), - vp_text_3: root.style.getPropertyValue('--vp-c-text-3') - }) - } catch (e) { - // ignore - } - // Apply button colors root.style.setProperty('--vp-button-brand-bg', colors.button.brand.bg) root.style.setProperty('--vp-button-brand-border', colors.button.brand.border) @@ -284,7 +276,7 @@ export class ThemeHandler { this.state.value.theme = themeRegistry[themeName] localStorage.setItem(STORAGE_KEY_THEME, themeName) this.applyTheme() - + // Force re-apply ColorPicker colors if theme doesn't specify brand colors this.ensureColorPickerColors() } @@ -297,10 +289,10 @@ export class ThemeHandler { public toggleMode() { const currentMode = this.state.value.currentMode - + // Toggle between light and dark const newMode: DisplayMode = currentMode === 'light' ? 'dark' : 'light' - + this.setMode(newMode) }