Skip to content

Commit a615bba

Browse files
committed
fix: prevent theme switcher from overwriting saved theme on mount
Wait for component to mount before attempting to write the current theme state to localStorage. This prevents the initial 'dracula' state from clobbering the user's saved preference before the initial read effect can update the state.
1 parent a4427a4 commit a615bba

1 file changed

Lines changed: 9 additions & 2 deletions

File tree

components/theme-switcher.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,28 @@ interface ThemeSwitcherProps {
3232
*/
3333
export function ThemeSwitcher({ className = '' }: ThemeSwitcherProps) {
3434
const [theme, setTheme] = useState<ThemeId>('dracula')
35+
const [mounted, setMounted] = useState(false)
3536
const validThemeIds = useMemo(() => new Set(THEME_OPTIONS.map((o) => o.id)), [])
3637

3738
useEffect(() => {
39+
setMounted(true)
3840
const saved = localStorage.getItem('terminal-theme')
3941
const attr = document.documentElement.getAttribute('data-theme')
4042
const initial = [saved, attr].find(
4143
(v): v is ThemeId => !!v && validThemeIds.has(v as ThemeId),
4244
)
43-
if (initial) setTheme(initial)
45+
if (initial) {
46+
setTheme(initial)
47+
// Apply immediately to avoid flash if state update takes a tick
48+
document.documentElement.setAttribute('data-theme', initial)
49+
}
4450
}, [validThemeIds])
4551

4652
useEffect(() => {
53+
if (!mounted) return
4754
document.documentElement.setAttribute('data-theme', theme)
4855
localStorage.setItem('terminal-theme', theme)
49-
}, [theme])
56+
}, [theme, mounted])
5057

5158
return (
5259
<label className={`inline-flex items-center gap-2 text-sm font-mono text-[var(--term-fg-dim)] ${className}`.trim()}>

0 commit comments

Comments
 (0)