mirror of
https://github.com/zvx-echo6/navi.git
synced 2026-05-20 22:54:42 +02:00
feat(themes): add theme picker with swatch previews and per-theme fonts
PART 1: Add missing CSS variables to all ui objects - Add --bg-inset, --bg-muted for component backgrounds - Add --success, --warning as aliases for --status-success/warning - Add --warning-muted for warning background states - Each theme now has 32 CSS variables PART 2: Per-theme font support - Move --font-sans and --font-mono from :root to ui objects - Add fontImports array to theme config (for future custom fonts) - applyThemeUI() now manages <link> tags for font imports - Existing themes use empty fontImports (system fonts already loaded) PART 3: Swatch preview colors - Add swatch array (3 hex colors) to each theme for visual preview - light: warm tan, sage green, khaki - dark: dark brown, sage green, tan - clean: light gray, Google blue, Google green - themeList() now returns swatch in result shape PART 4: Theme picker UI - New ThemePicker component replaces icon toggle in header - Palette icon trigger opens popover below - Shows all themes as circular swatches (conic gradient) - Active theme has accent ring indicator - Click swatch to apply theme, closes popover - Click outside or Escape closes popover - Styled with current theme CSS variables Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
7ec87f0945
commit
a7fd4e4e8c
5 changed files with 263 additions and 53 deletions
|
|
@ -1,6 +1,6 @@
|
|||
import { useRef, useCallback, useEffect, useState } from 'react'
|
||||
import { Sun, Moon, Sparkles, LogIn, LogOut } from 'lucide-react'
|
||||
import { themeList } from '../themes/registry'
|
||||
import { LogIn, LogOut } from 'lucide-react'
|
||||
import ThemePicker from './ThemePicker'
|
||||
import { useStore, usePanelState } from '../store'
|
||||
import { hasFeature } from '../config'
|
||||
import SearchBar from './SearchBar'
|
||||
|
|
@ -55,32 +55,6 @@ export default function Panel({ onManeuverClick }) {
|
|||
return () => window.removeEventListener('resize', check)
|
||||
}, [])
|
||||
|
||||
// Theme toggle - cycles through all available themes
|
||||
const toggleTheme = () => {
|
||||
const themes = themeList()
|
||||
const currentIdx = themes.findIndex(t => t.id === theme)
|
||||
const nextIdx = (currentIdx + 1) % themes.length
|
||||
setThemeOverride(themes[nextIdx].id)
|
||||
}
|
||||
|
||||
// Get theme icon based on current theme
|
||||
const getThemeIcon = () => {
|
||||
switch (theme) {
|
||||
case 'dark': return <Moon size={16} />
|
||||
case 'light': return <Sun size={16} />
|
||||
case 'clean': return <Sparkles size={16} />
|
||||
default: return <Sun size={16} />
|
||||
}
|
||||
}
|
||||
|
||||
// Get next theme name for tooltip
|
||||
const getNextThemeName = () => {
|
||||
const themes = themeList()
|
||||
const currentIdx = themes.findIndex(t => t.id === theme)
|
||||
const nextIdx = (currentIdx + 1) % themes.length
|
||||
return themes[nextIdx].name
|
||||
}
|
||||
|
||||
// Auth handlers
|
||||
const handleLogin = () => { window.location.href = '/outpost.goauthentik.io/start?rd=%2F' }
|
||||
const handleLogout = () => { window.location.href = 'https://auth.echo6.co/if/flow/default-invalidation-flow/?next=https://navi.echo6.co/' }
|
||||
|
|
@ -274,15 +248,7 @@ export default function Panel({ onManeuverClick }) {
|
|||
</button>
|
||||
)
|
||||
)}
|
||||
<button
|
||||
onClick={toggleTheme}
|
||||
className="p-1.5 rounded"
|
||||
style={{ color: 'var(--text-secondary)' }}
|
||||
aria-label={`Switch to ${getNextThemeName()} theme`}
|
||||
title={`Switch to ${getNextThemeName()} theme`}
|
||||
>
|
||||
{getThemeIcon()}
|
||||
</button>
|
||||
<ThemePicker />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue