diff --git a/app/src/App.tsx b/app/src/App.tsx index 07f592c..8169f28 100644 --- a/app/src/App.tsx +++ b/app/src/App.tsx @@ -5,6 +5,7 @@ import { TopBar } from "./TopBar"; import { CenterToolbar } from "./CenterToolbar"; import { Wizard } from "./Wizard"; import { ConfirmDelete } from "./ConfirmDelete"; +import { Settings } from "./Settings"; import { EventCenter } from "./EventCenter"; import { maybeNotify } from "./notify"; import { COLORS, applyTheme, resolvePalette } from "./theme"; @@ -31,6 +32,7 @@ export function App() { const [events, setEvents] = useState([]); const [wizard, setWizard] = useState(false); const [deleteTarget, setDeleteTarget] = useState(null); + const [settingsOpen, setSettingsOpen] = useState(false); const [eventsOpen, setEventsOpen] = useState(() => loadFlag("spacesh.eventsOpen", true)); const [sidebarOpen, setSidebarOpen] = useState(() => loadFlag("spacesh.sidebarOpen", true)); const [health, setHealth] = useState(null); @@ -147,7 +149,7 @@ export function App() { return (
- setEventsOpen((v) => !v)} onShowEvents={() => setEventsOpen(true)} sidebarOpen={sidebarOpen} onToggleSidebar={() => setSidebarOpen((v) => !v)} unread={unread} /> + setEventsOpen((v) => !v)} onShowEvents={() => setEventsOpen(true)} sidebarOpen={sidebarOpen} onToggleSidebar={() => setSidebarOpen((v) => !v)} unread={unread} onOpenSettings={() => setSettingsOpen(true)} />
{sidebarOpen && setWizard(true)} onDelete={setDeleteTarget} health={health} connected={connected} />}
@@ -168,6 +170,7 @@ export function App() { /> )}
+ {settingsOpen && config && setSettingsOpen(false)} />} {wizard && { setWizard(false); setActiveId(id); void refresh(); }} onCancel={() => setWizard(false)} />} {deleteTarget && ( void }) { + const ref = useRef(null); + useEffect(() => { ref.current?.focus(); }, []); + return ( +
+
e.stopPropagation()} onKeyDown={(e) => { e.stopPropagation(); if (e.key === "Escape") onClose(); }} + style={{ width: 520, maxHeight: "80vh", overflowY: "auto", background: COLORS.bgApp, border: `1px solid ${COLORS.borderStrong}`, borderRadius: 14, padding: 24, color: COLORS.textPrimary, fontFamily: FONT.ui }}> +
Settings
+ +
Terminal font
+ +
+ Size {config.font_size} + void setConfig({ font_size: Number(e.target.value) })} style={{ flex: 1 }} /> +
+ +
Theme
+
+ {(["dark", "light"] as const).map((t) => ( + + ))} +
+
Accent
+
+ {ACCENTS.map((a) => ( +
+ +
Default shell (empty = auto)
+ void setConfig({ default_shell: e.target.value })} + style={{ width: "100%", padding: 8, marginBottom: 18, background: COLORS.bgPanel, color: COLORS.textPrimary, border: `1px solid ${COLORS.borderStrong}`, borderRadius: 8 }} /> + + +
+
+ ); +} + +// Placeholder — fleshed out in Task 11. Keep the signature stable. +function DaemonSection(_props: { health: DaemonHealth | null }) { return null; } diff --git a/app/src/TopBar.tsx b/app/src/TopBar.tsx index df90abc..fbff10c 100644 --- a/app/src/TopBar.tsx +++ b/app/src/TopBar.tsx @@ -29,7 +29,7 @@ function IconBtn({ icon, onClick, active, title }: { icon: React.ReactNode; onCl } export function TopBar({ - active, eventsOpen, onToggleEvents, onShowEvents, sidebarOpen, onToggleSidebar, unread, + active, eventsOpen, onToggleEvents, onShowEvents, sidebarOpen, onToggleSidebar, unread, onOpenSettings, }: { active: WorkspaceView | null; eventsOpen: boolean; @@ -38,6 +38,7 @@ export function TopBar({ sidebarOpen: boolean; onToggleSidebar: () => void; unread: number; + onOpenSettings: () => void; }) { return (
} onClick={onToggleEvents} active={eventsOpen} title="Toggle Event Center" /> - } title="Settings (mock)" /> + } onClick={onOpenSettings} title="Settings" />