feat: add dark theme support with CSS custom properties and Naive UI integration

Implement runtime theme switching using CSS custom properties delegated through SCSS variables, with light/dark/system modes, FOUC prevention, sidebar toggle, and settings selector. Add theme-aware video assets for sidebar and chat thinking indicator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
ekko
2026-04-16 23:13:04 +08:00
parent 076a7c2a38
commit b5aeb876b8
32 changed files with 465 additions and 126 deletions
@@ -0,0 +1,57 @@
import { ref, watch } from 'vue'
export type ThemeMode = 'light' | 'dark' | 'system'
const STORAGE_KEY = 'hermes_theme'
const mode = ref<ThemeMode>(
(localStorage.getItem(STORAGE_KEY) as ThemeMode) || 'system',
)
const isDark = ref(false)
function applyTheme(dark: boolean) {
isDark.value = dark
document.documentElement.classList.toggle('dark', dark)
}
function resolveDark(m: ThemeMode): boolean {
if (m === 'system') {
return window.matchMedia('(prefers-color-scheme: dark)').matches
}
return m === 'dark'
}
// Initial resolve
applyTheme(resolveDark(mode.value))
// Listen for system preference changes
const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)')
mediaQuery.addEventListener('change', () => {
if (mode.value === 'system') {
applyTheme(true)
}
})
// Watch mode changes
watch(mode, (newMode) => {
localStorage.setItem(STORAGE_KEY, newMode)
applyTheme(resolveDark(newMode))
})
export function useTheme() {
function setMode(m: ThemeMode) {
mode.value = m
}
function toggleTheme() {
mode.value = isDark.value ? 'light' : 'dark'
}
return {
mode,
isDark,
setMode,
toggleTheme,
}
}