feat: Add Canvas dark theme styling and Setup page integration

Canvas Builder Visual Updates:
- Update all Canvas components to use Atomaster dark theme
- BaseNode: dark background (bg-dark-800), white text, primary selection glow
- NodePalette: dark sidebar with hover states
- NodeConfigPanel: dark inputs, labels, and panel background
- ValidationPanel: semi-transparent error/warning panels with backdrop blur
- ChatPanel: dark message area with themed welcome state
- ExecuteDialog: dark modal with primary button styling
- ConfigImporter: dark tabs, inputs, and file upload zone
- TemplateSelector: dark cards with category pills and hover effects

Setup Page Integration:
- Add Configuration/Canvas Builder tab switcher
- Canvas tab renders AtomizerCanvas full-height
- Tabs styled to match Atomaster theme

Build: Passes TypeScript and Vite build

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-14 21:30:30 -05:00
parent 92c82a5518
commit 9f3ac28000
10 changed files with 221 additions and 153 deletions

View File

@@ -19,12 +19,15 @@ import {
Info,
FileBox,
FolderOpen,
File
File,
Layout,
Grid3X3
} from 'lucide-react';
import { useStudy } from '../context/StudyContext';
import { Card } from '../components/common/Card';
import { Button } from '../components/common/Button';
import { apiClient, ModelFile } from '../api/client';
import { AtomizerCanvas } from '../components/canvas/AtomizerCanvas';
interface StudyConfig {
study_name: string;
@@ -71,9 +74,12 @@ interface StudyConfig {
}[];
}
type TabType = 'config' | 'canvas';
export default function Setup() {
const navigate = useNavigate();
const { selectedStudy, isInitialized } = useStudy();
const [activeTab, setActiveTab] = useState<TabType>('config');
const [config, setConfig] = useState<StudyConfig | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
@@ -248,8 +254,59 @@ export default function Setup() {
return acc * 1000; // Approximate for continuous
}, 1) || 0;
// Canvas tab - full height
if (activeTab === 'canvas') {
return (
<div className="w-full h-full flex flex-col">
{/* Tab Bar */}
<div className="flex items-center gap-2 mb-4 border-b border-dark-700 pb-4">
<button
onClick={() => setActiveTab('config')}
className="flex items-center gap-2 px-4 py-2 rounded-lg transition-colors bg-dark-800 text-dark-300 hover:text-white hover:bg-dark-700"
>
<Layout className="w-4 h-4" />
Configuration
</button>
<button
onClick={() => setActiveTab('canvas')}
className="flex items-center gap-2 px-4 py-2 rounded-lg transition-colors bg-primary-600 text-white"
>
<Grid3X3 className="w-4 h-4" />
Canvas Builder
</button>
<div className="flex-1" />
<span className="text-dark-400 text-sm">
{selectedStudy?.name || 'Study'}
</span>
</div>
{/* Canvas - takes remaining height */}
<div className="flex-1 min-h-0 rounded-lg overflow-hidden border border-dark-700">
<AtomizerCanvas />
</div>
</div>
);
}
return (
<div className="w-full">
{/* Tab Bar */}
<div className="flex items-center gap-2 mb-4">
<button
onClick={() => setActiveTab('config')}
className="flex items-center gap-2 px-4 py-2 rounded-lg transition-colors bg-primary-600 text-white"
>
<Layout className="w-4 h-4" />
Configuration
</button>
<button
onClick={() => setActiveTab('canvas')}
className="flex items-center gap-2 px-4 py-2 rounded-lg transition-colors bg-dark-800 text-dark-300 hover:text-white hover:bg-dark-700"
>
<Grid3X3 className="w-4 h-4" />
Canvas Builder
</button>
</div>
{/* Header */}
<header className="mb-6 flex items-center justify-between border-b border-dark-600 pb-4">
<div>