Major improvements to UI state management and user preferences: - Add theme toggle with dark/light mode support - Implement Zustand persist middleware for UI state - Add ui-store for panel layout preferences (dock width, heights, tabs) - Persist tool settings (active tool, size, opacity, hardness, etc.) - Persist canvas view preferences (grid, rulers, snap-to-grid) - Persist shape tool settings - Persist collapsible section states - Fix canvas coordinate transformation for centered rendering - Constrain checkerboard and grid to canvas bounds - Add icons to all tab buttons and collapsible sections - Restructure panel-dock to use persisted state Storage impact: ~3.5KB total across all preferences Storage keys: tool-storage, canvas-view-storage, shape-storage, ui-storage 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
56 lines
1.4 KiB
TypeScript
56 lines
1.4 KiB
TypeScript
'use client';
|
|
|
|
import { useEffect, useState } from 'react';
|
|
import { Moon, Sun } from 'lucide-react';
|
|
|
|
export function ThemeToggle() {
|
|
const [theme, setTheme] = useState<'light' | 'dark'>('light');
|
|
const [mounted, setMounted] = useState(false);
|
|
|
|
useEffect(() => {
|
|
setMounted(true);
|
|
const savedTheme = localStorage.getItem('theme');
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
const currentTheme = savedTheme === 'dark' || (!savedTheme && prefersDark) ? 'dark' : 'light';
|
|
setTheme(currentTheme);
|
|
}, []);
|
|
|
|
const toggleTheme = () => {
|
|
const newTheme = theme === 'light' ? 'dark' : 'light';
|
|
setTheme(newTheme);
|
|
localStorage.setItem('theme', newTheme);
|
|
|
|
if (newTheme === 'dark') {
|
|
document.documentElement.classList.add('dark');
|
|
} else {
|
|
document.documentElement.classList.remove('dark');
|
|
}
|
|
};
|
|
|
|
// Prevent hydration mismatch
|
|
if (!mounted) {
|
|
return (
|
|
<button
|
|
className="rounded-md p-2 text-muted-foreground"
|
|
disabled
|
|
>
|
|
<Sun className="h-4 w-4" />
|
|
</button>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<button
|
|
onClick={toggleTheme}
|
|
className="rounded-md p-2 hover:bg-accent transition-colors"
|
|
title={`Switch to ${theme === 'light' ? 'dark' : 'light'} mode`}
|
|
>
|
|
{theme === 'light' ? (
|
|
<Moon className="h-4 w-4" />
|
|
) : (
|
|
<Sun className="h-4 w-4" />
|
|
)}
|
|
</button>
|
|
);
|
|
}
|