diff --git a/apps/desktop/src/renderer/index.html b/apps/desktop/src/renderer/index.html index 61e7933a..9c339e8c 100644 --- a/apps/desktop/src/renderer/index.html +++ b/apps/desktop/src/renderer/index.html @@ -14,6 +14,16 @@
+ diff --git a/apps/desktop/src/renderer/src/App.tsx b/apps/desktop/src/renderer/src/App.tsx index e761430c..e0ef2917 100644 --- a/apps/desktop/src/renderer/src/App.tsx +++ b/apps/desktop/src/renderer/src/App.tsx @@ -1,131 +1,86 @@ -import { buildSrcdoc } from '@open-codesign/runtime'; -import { BUILTIN_DEMOS } from '@open-codesign/templates'; -import { Button } from '@open-codesign/ui'; -import { Send, Sparkles } from 'lucide-react'; -import { useState } from 'react'; +import { useMemo, useState } from 'react'; +import { CommandPalette } from './components/CommandPalette'; +import { PreviewPane } from './components/PreviewPane'; +import { Settings } from './components/Settings'; +import { Sidebar } from './components/Sidebar'; +import { ToastViewport } from './components/Toast'; +import { TopBar } from './components/TopBar'; +import { useKeyboard } from './hooks/useKeyboard'; import { useCodesignStore } from './store'; export function App() { - const messages = useCodesignStore((s) => s.messages); - const previewHtml = useCodesignStore((s) => s.previewHtml); - const isGenerating = useCodesignStore((s) => s.isGenerating); const sendPrompt = useCodesignStore((s) => s.sendPrompt); + const isGenerating = useCodesignStore((s) => s.isGenerating); + const openSettings = useCodesignStore((s) => s.openSettings); + const closeSettings = useCodesignStore((s) => s.closeSettings); + const openCommandPalette = useCodesignStore((s) => s.openCommandPalette); + const closeCommandPalette = useCodesignStore((s) => s.closeCommandPalette); + const settingsOpen = useCodesignStore((s) => s.settingsOpen); + const commandPaletteOpen = useCodesignStore((s) => s.commandPaletteOpen); + const [prompt, setPrompt] = useState(''); - function handleSubmit(e: React.FormEvent) { - e.preventDefault(); - if (!prompt.trim() || isGenerating) return; - void sendPrompt(prompt); + function submit() { + const trimmed = prompt.trim(); + if (!trimmed || isGenerating) return; + void sendPrompt(trimmed); setPrompt(''); } - return ( -
- + const bindings = useMemo( + () => [ + { + combo: 'mod+enter', + handler: () => { + const trimmed = prompt.trim(); + if (!trimmed || isGenerating) return; + void sendPrompt(trimmed); + setPrompt(''); + }, + }, + { + combo: 'mod+,', + handler: () => openSettings(), + }, + { + combo: 'mod+k', + handler: () => openCommandPalette(), + }, + { + combo: 'escape', + handler: () => { + if (settingsOpen) closeSettings(); + else if (commandPaletteOpen) closeCommandPalette(); + }, + preventDefault: false, + }, + ], + [ + prompt, + isGenerating, + sendPrompt, + settingsOpen, + commandPaletteOpen, + openSettings, + openCommandPalette, + closeSettings, + closeCommandPalette, + ], + ); + useKeyboard(bindings); -
-
- - {previewHtml ? 'Preview' : 'No design yet'} - - - BYOK · local-first · multi-model - -
-
- {previewHtml ? ( -