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:
1 parent
78c5f0f1b0
commit
5faa955bce
24 files changed
+337
-218
No files matched your search
@@ -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 })
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in new issue
Block a user