From 6d70c5f8a3ed90564b08616a3fb041409916059c Mon Sep 17 00:00:00 2001 From: Clawd Date: Sat, 28 Feb 2026 07:30:40 -0800 Subject: Phase 4: React UI - Add renderer/src/types.ts with Project, Session, Message, Phase types - Add renderer/src/styles/globals.css with full styling - Dark theme with accent colors - Header, document pane, chat pane, action bar layouts - Phase indicator, token usage bar, buttons - Add renderer/src/components/Header.tsx - Project/session dropdowns with create buttons - Phase indicator showing current workflow state - Add renderer/src/components/DocumentPane.tsx - Markdown viewer/editor with toggle - Syntax highlighting for review comments - Task checkbox rendering - Add renderer/src/components/ChatPane.tsx - Message list with auto-scroll - Input field with Enter to send - Loading state indicator - Add renderer/src/components/ActionBar.tsx - Token usage bar with color coding - Review/Submit buttons for workflow - Permission mode toggle for implement phase - Add renderer/src/App.tsx - Full state management for projects, sessions, messages - Claude message subscription - Workflow handlers (review, submit, phase advance) - Update renderer/src/main.tsx to render App --- renderer/src/components/ChatPane.tsx | 66 ++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 renderer/src/components/ChatPane.tsx (limited to 'renderer/src/components/ChatPane.tsx') diff --git a/renderer/src/components/ChatPane.tsx b/renderer/src/components/ChatPane.tsx new file mode 100644 index 0000000..917d462 --- /dev/null +++ b/renderer/src/components/ChatPane.tsx @@ -0,0 +1,66 @@ +import React, { useState, useRef, useEffect } from "react"; +import type { Message } from "../types"; + +interface ChatPaneProps { + messages: Message[]; + onSend: (message: string) => void; + isLoading: boolean; + disabled: boolean; + placeholder: string; +} + +export function ChatPane({ + messages, + onSend, + isLoading, + disabled, + placeholder, +}: ChatPaneProps) { + const [input, setInput] = useState(""); + const messagesEndRef = useRef(null); + + useEffect(() => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + }, [messages]); + + const handleSend = () => { + if (!input.trim() || isLoading || disabled) return; + onSend(input.trim()); + setInput(""); + }; + + return ( +
+
+ {messages.map((msg) => ( +
+
{msg.content}
+
+ ))} + {isLoading && ( +
+
Thinking...
+
+ )} +
+
+ +
+ setInput(e.target.value)} + onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && handleSend()} + placeholder={placeholder} + disabled={disabled || isLoading} + /> + +
+
+ ); +} -- cgit v1.2.3