feat(frontend): integrate ThemeSwitcher, restore custom palette on page load
This commit is contained in:
parent
ce29eb3062
commit
7736869fc4
@ -10,9 +10,24 @@ import {
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
} from '@/components/ui/dropdown-menu';
|
||||
import {BookOpen, Box, ChevronDown, Compass, Home, LayoutGrid, Monitor, Moon, Plus, Sun, Users} from 'lucide-react';
|
||||
import {
|
||||
BookOpen,
|
||||
Box,
|
||||
ChevronDown,
|
||||
Compass,
|
||||
Home,
|
||||
LayoutGrid,
|
||||
Monitor,
|
||||
Moon,
|
||||
Plus,
|
||||
Sliders,
|
||||
Sun,
|
||||
Users
|
||||
} from 'lucide-react';
|
||||
import {useNavigate} from 'react-router-dom';
|
||||
import {Avatar, AvatarFallback, AvatarImage} from '@/components/ui/avatar';
|
||||
import {useState} from 'react';
|
||||
import {ThemeSwitcher} from '@/components/room/ThemeSwitcher';
|
||||
|
||||
const btnClass = 'flex w-full h-9 justify-start items-center rounded-md font-medium hover:bg-muted cursor-pointer bg-transparent border-0 text-left text-sm';
|
||||
|
||||
@ -22,10 +37,10 @@ export function SidebarSystem({collapsed}: {collapsed: boolean}) {
|
||||
const workspaceCtx = tryUseWorkspace();
|
||||
const workspaces = workspaceCtx?.workspaces;
|
||||
const currentWorkspace = workspaceCtx?.currentWorkspace;
|
||||
const [themeSheetOpen, setThemeSheetOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
{/* Workspace switcher — only shown when inside WorkspaceProvider */}
|
||||
{workspaceCtx && (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger
|
||||
@ -88,29 +103,33 @@ export function SidebarSystem({collapsed}: {collapsed: boolean}) {
|
||||
</DropdownMenu>
|
||||
)}
|
||||
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/')}>
|
||||
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
|
||||
onClick={() => navigate('/')}>
|
||||
<span className={cn('flex h-6 w-6 items-center justify-center shrink-0')}>
|
||||
<Home className="h-4 w-4"/>
|
||||
</span>
|
||||
{!collapsed && <span className="text-sm leading-none">Home</span>}
|
||||
</button>
|
||||
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/explore')}>
|
||||
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
|
||||
onClick={() => navigate('/explore')}>
|
||||
<span className={cn('flex h-6 w-6 items-center justify-center shrink-0')}>
|
||||
<Compass className="h-4 w-4"/>
|
||||
</span>
|
||||
{!collapsed && <span className="text-sm leading-none">Explore</span>}
|
||||
</button>
|
||||
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => navigate('/market')}>
|
||||
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
|
||||
onClick={() => navigate('/market')}>
|
||||
<span className={cn('flex h-6 w-6 items-center justify-center shrink-0')}>
|
||||
<Box className="h-4 w-4"/>
|
||||
</span>
|
||||
{!collapsed && <span className="text-sm leading-none">Marketplace</span>}
|
||||
</button>
|
||||
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')} onClick={() => window.open('/docs', '_blank')}>
|
||||
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
||||
<button type="button" className={cn(btnClass, collapsed ? 'justify-center px-0' : 'px-2')}
|
||||
onClick={() => window.open('/docs', '_blank')}>
|
||||
<span className={cn('flex h-6 w-6 items-center justify-center shrink-0')}>
|
||||
<BookOpen className="h-4 w-4"/>
|
||||
</span>
|
||||
{!collapsed && <span className="text-sm leading-none">Docs</span>}
|
||||
@ -125,7 +144,7 @@ export function SidebarSystem({collapsed}: {collapsed: boolean}) {
|
||||
/>
|
||||
}
|
||||
>
|
||||
<span className={cn('flex h-6 items-center shrink-0', collapsed ? 'w-6 justify-center' : 'w-6')}>
|
||||
<span className={cn('flex h-6 w-6 items-center justify-center shrink-0')}>
|
||||
{theme === 'dark' ? (
|
||||
<Moon className="h-4 w-4"/>
|
||||
) : theme === 'light' ? (
|
||||
@ -139,7 +158,12 @@ export function SidebarSystem({collapsed}: {collapsed: boolean}) {
|
||||
<DropdownMenuContent side="right" align="start">
|
||||
{!collapsed && (
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuLabel>Theme Settings</DropdownMenuLabel>
|
||||
<DropdownMenuLabel>Theme</DropdownMenuLabel>
|
||||
<DropdownMenuItem onClick={() => setThemeSheetOpen(true)}>
|
||||
<Sliders className="mr-2 h-4 w-4"/>
|
||||
<span>Design System</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuSeparator/>
|
||||
<DropdownMenuItem onClick={() => setTheme('light')}>
|
||||
<Sun className="mr-2 h-4 w-4"/>
|
||||
<span>Light</span>
|
||||
@ -155,20 +179,13 @@ export function SidebarSystem({collapsed}: {collapsed: boolean}) {
|
||||
</DropdownMenuGroup>
|
||||
)}
|
||||
{collapsed && (
|
||||
<>
|
||||
<DropdownMenuItem onClick={() => setTheme('light')}>
|
||||
<Sun className="mr-2 h-4 w-4" />
|
||||
<DropdownMenuItem onClick={() => setThemeSheetOpen(true)}>
|
||||
<Sliders className="mr-2 h-4 w-4"/>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('dark')}>
|
||||
<Moon className="mr-2 h-4 w-4" />
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={() => setTheme('system')}>
|
||||
<Monitor className="mr-2 h-4 w-4" />
|
||||
</DropdownMenuItem>
|
||||
</>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<ThemeSwitcher open={themeSheetOpen} onOpenChange={setThemeSheetOpen}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
14
src/main.tsx
14
src/main.tsx
@ -6,6 +6,20 @@ import {UserProvider} from '@/contexts';
|
||||
import {ThemeProvider} from '@/contexts/theme-context';
|
||||
import './index.css';
|
||||
import App from './App.tsx';
|
||||
import {applyPaletteToDOM, loadActivePresetId} from '@/components/room/design-system';
|
||||
|
||||
// Restore custom palette on page load (before first render)
|
||||
const activePreset = loadActivePresetId();
|
||||
if (activePreset === 'custom') {
|
||||
const customPalette = localStorage.getItem('theme-custom-palette');
|
||||
if (customPalette) {
|
||||
try {
|
||||
applyPaletteToDOM(JSON.parse(customPalette));
|
||||
} catch {
|
||||
// ignore malformed stored palette
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user