49 lines
1.9 KiB
TypeScript
49 lines
1.9 KiB
TypeScript
|
|
// App appearance prefs (theme + a few visual knobs), persisted to localStorage
|
||
|
|
// and applied by toggling attributes / CSS variables on <html>. Kept out of a
|
||
|
|
// component module so it can be imported anywhere (and called once at boot in
|
||
|
|
// main.tsx before React renders, to avoid a dark→light flash).
|
||
|
|
|
||
|
|
export type ThemeMode = 'dark' | 'light'
|
||
|
|
|
||
|
|
export interface AppearancePrefs {
|
||
|
|
theme: ThemeMode
|
||
|
|
fontSize: number // base font-size in px
|
||
|
|
radius: number // card border-radius in px
|
||
|
|
animations: boolean
|
||
|
|
}
|
||
|
|
|
||
|
|
const PREFS_KEY = 'archnest-appearance-prefs'
|
||
|
|
|
||
|
|
export function defaultAppearance(): AppearancePrefs {
|
||
|
|
return { theme: 'dark', fontSize: 14, radius: 12, animations: true }
|
||
|
|
}
|
||
|
|
|
||
|
|
export function loadAppearance(): AppearancePrefs {
|
||
|
|
try {
|
||
|
|
const raw = localStorage.getItem(PREFS_KEY)
|
||
|
|
if (raw) return { ...defaultAppearance(), ...JSON.parse(raw) }
|
||
|
|
} catch {
|
||
|
|
/* ignore malformed local storage */
|
||
|
|
}
|
||
|
|
return defaultAppearance()
|
||
|
|
}
|
||
|
|
|
||
|
|
export function saveAppearance(prefs: AppearancePrefs) {
|
||
|
|
localStorage.setItem(PREFS_KEY, JSON.stringify(prefs))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Apply prefs to the document. Light mode flips data-theme="light" (which the
|
||
|
|
// CSS variable overrides in index.css key off of); dark removes the attribute.
|
||
|
|
// ponytail: only theme is wired to real CSS right now; fontSize/radius/animations
|
||
|
|
// are persisted and exposed as CSS vars for components to opt into later — the
|
||
|
|
// app still mostly hardcodes hex, so a full token migration is a separate task
|
||
|
|
// (tracked in ROADMAP "Appearance section").
|
||
|
|
export function applyAppearance(prefs: AppearancePrefs) {
|
||
|
|
const root = document.documentElement
|
||
|
|
if (prefs.theme === 'light') root.setAttribute('data-theme', 'light')
|
||
|
|
else root.removeAttribute('data-theme')
|
||
|
|
root.style.setProperty('--app-font-size', `${prefs.fontSize}px`)
|
||
|
|
root.style.setProperty('--card-radius', `${prefs.radius}px`)
|
||
|
|
root.style.setProperty('--app-animations', prefs.animations ? '1' : '0')
|
||
|
|
}
|