From a9ae7c65c387bcf144de8df0a13dbbfd7496cc1e Mon Sep 17 00:00:00 2001 From: Clawd Date: Sat, 28 Feb 2026 15:21:27 -0800 Subject: Restyle UI with light/dark theme support - Add light/dark theme toggle with localStorage persistence - Add 'Claude Flow' wordmark in header - Switch to monospace font (SF Mono, Cascadia Code, etc.) - Update accent colors (lighter blue) - Add theme-aware CodeMirror styling (oneDark vs defaultHighlightStyle) - Update window title to 'Claude Flow' - Refine spacing and visual polish throughout - Add .claude-flow/ artifacts from self-restyling session --- renderer/src/App.tsx | 18 +++ renderer/src/components/DocumentPane.tsx | 10 +- renderer/src/components/Header.tsx | 14 ++ renderer/src/styles/globals.css | 259 +++++++++++++++++++++---------- 4 files changed, 218 insertions(+), 83 deletions(-) (limited to 'renderer/src') diff --git a/renderer/src/App.tsx b/renderer/src/App.tsx index 26ac252..5ca7a9b 100644 --- a/renderer/src/App.tsx +++ b/renderer/src/App.tsx @@ -8,6 +8,8 @@ import "./styles/globals.css"; const api = window.api; +type Theme = "dark" | "light"; + export function App() { const [projects, setProjects] = useState([]); const [sessions, setSessions] = useState([]); @@ -23,6 +25,19 @@ export function App() { }); const [error, setError] = useState(null); + const [theme, setTheme] = useState( + () => (localStorage.getItem("cf-theme") as Theme) ?? "dark" + ); + + // Keep document.documentElement in sync and persist to localStorage + useEffect(() => { + document.documentElement.setAttribute("data-theme", theme); + localStorage.setItem("cf-theme", theme); + }, [theme]); + + const handleToggleTheme = () => + setTheme((t) => (t === "dark" ? "light" : "dark")); + const hasChanges = documentContent !== originalContent; // Clear error after 5 seconds @@ -282,6 +297,8 @@ export function App() { onCreateSession={handleCreateSession} onDeleteProject={handleDeleteProject} onDeleteSession={handleDeleteSession} + theme={theme} + onToggleTheme={handleToggleTheme} />
@@ -291,6 +308,7 @@ export function App() { phase={selectedSession?.phase || "research"} disabled={!selectedSession || selectedSession.phase === "implement"} showOnboarding={!selectedProject} + theme={theme} /> void; disabled: boolean; + theme: "dark" | "light"; }) { const editorRef = useRef(null); const viewRef = useRef(null); @@ -47,7 +51,7 @@ function MarkdownEditor({ history(), keymap.of([...defaultKeymap, ...historyKeymap]), markdown({ codeLanguages: languages }), - oneDark, + theme === "dark" ? oneDark : syntaxHighlighting(defaultHighlightStyle), updateListener, EditorView.editable.of(!disabled), EditorView.lineWrapping, @@ -81,7 +85,7 @@ function MarkdownEditor({ view.destroy(); viewRef.current = null; }; - }, [disabled]); + }, [disabled, theme]); // Update content when it changes externally useEffect(() => { @@ -109,6 +113,7 @@ export function DocumentPane({ phase, disabled, showOnboarding, + theme, }: DocumentPaneProps) { const [isEditing, setIsEditing] = useState(false); @@ -211,6 +216,7 @@ export function DocumentPane({ content={content} onChange={onChange} disabled={disabled} + theme={theme} /> ) : (
void; onDeleteProject?: (id: string) => void; onDeleteSession?: (id: string) => void; + theme: Theme; + onToggleTheme: () => void; } const phaseLabels: Record = { @@ -33,6 +37,8 @@ export function Header({ onCreateSession, onDeleteProject, onDeleteSession, + theme, + onToggleTheme, }: HeaderProps) { const handleDeleteProject = () => { if (!selectedProject || !onDeleteProject) return; @@ -51,6 +57,9 @@ export function Header({ return (
+ {/* ── Wordmark ── */} + Claude Flow +