feat(ui): add light theme with system auto-switch + Cyrene avatar

- Miuix day/night dual theme CSS variables
- themeStore: light default, follows prefers-color-scheme
- Header: sun/moon toggle button
- All components migrated to CSS variables
- Cyrene avatar image replaces 'C' logo everywhere
- Favicon added
This commit is contained in:
Aska committed 2026-08-12 17:42:18 +08:00
1 parent 78c5f0f1b0
commit 5faa955bce
24 files changed
+337 -218

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
import { create } from 'zustand'
type Theme = 'light' | 'dark'
function getSystemTheme(): Theme {
if (typeof window === 'undefined') return 'light'
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'
}
function getStoredTheme(): Theme | null {
try {
const stored = localStorage.getItem('cyrene_theme')
if (stored === 'light' || stored === 'dark') return stored
} catch {}
return null
}
interface ThemeState {
theme: Theme
setTheme: (t: Theme) => void
toggle: () => void
}
export const useThemeStore = create<ThemeState>((set, get) => ({
theme: getStoredTheme() || 'light',
setTheme: (t: Theme) => {
document.documentElement.setAttribute('data-theme', t)
localStorage.setItem('cyrene_theme', t)
set({ theme: t })
},
toggle: () => {
const next = get().theme === 'dark' ? 'light' : 'dark'
get().setTheme(next)
},
}))
// Initialize theme on app start
if (typeof document !== 'undefined') {
const stored = getStoredTheme()
if (stored) {
document.documentElement.setAttribute('data-theme', stored)
} else {
// Follow system preference
const sys = getSystemTheme()
document.documentElement.setAttribute('data-theme', sys)
}
// Listen for system theme changes
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
if (!getStoredTheme()) {
const sys = e.matches ? 'dark' : 'light'
document.documentElement.setAttribute('data-theme', sys)
useThemeStore.setState({ theme: sys })
}
})
}