diff options
Diffstat (limited to 'renderer/src/components')
| -rw-r--r-- | renderer/src/components/ChatPane.tsx | 80 |
1 files changed, 51 insertions, 29 deletions
diff --git a/renderer/src/components/ChatPane.tsx b/renderer/src/components/ChatPane.tsx index 917d462..40e682c 100644 --- a/renderer/src/components/ChatPane.tsx +++ b/renderer/src/components/ChatPane.tsx | |||
| @@ -7,6 +7,9 @@ interface ChatPaneProps { | |||
| 7 | isLoading: boolean; | 7 | isLoading: boolean; |
| 8 | disabled: boolean; | 8 | disabled: boolean; |
| 9 | placeholder: string; | 9 | placeholder: string; |
| 10 | collapsed: boolean; | ||
| 11 | chatWidth: number; | ||
| 12 | onToggleCollapse: () => void; | ||
| 10 | } | 13 | } |
| 11 | 14 | ||
| 12 | export function ChatPane({ | 15 | export function ChatPane({ |
| @@ -15,6 +18,9 @@ export function ChatPane({ | |||
| 15 | isLoading, | 18 | isLoading, |
| 16 | disabled, | 19 | disabled, |
| 17 | placeholder, | 20 | placeholder, |
| 21 | collapsed, | ||
| 22 | chatWidth, | ||
| 23 | onToggleCollapse, | ||
| 18 | }: ChatPaneProps) { | 24 | }: ChatPaneProps) { |
| 19 | const [input, setInput] = useState(""); | 25 | const [input, setInput] = useState(""); |
| 20 | const messagesEndRef = useRef<HTMLDivElement>(null); | 26 | const messagesEndRef = useRef<HTMLDivElement>(null); |
| @@ -30,37 +36,53 @@ export function ChatPane({ | |||
| 30 | }; | 36 | }; |
| 31 | 37 | ||
| 32 | return ( | 38 | return ( |
| 33 | <div className="chat-pane"> | 39 | <div |
| 34 | <div className="chat-messages"> | 40 | className="chat-pane" |
| 35 | {messages.map((msg) => ( | 41 | style={{ width: collapsed ? 28 : chatWidth }} |
| 36 | <div key={msg.id} className={`message ${msg.role}`}> | 42 | > |
| 37 | <div className="message-content">{msg.content}</div> | 43 | <div className="chat-header"> |
| 38 | </div> | 44 | {!collapsed && <span>Chat</span>} |
| 39 | ))} | 45 | <button className="chat-collapse-btn" onClick={onToggleCollapse}> |
| 40 | {isLoading && ( | 46 | {collapsed ? "⟨" : "⟩"} |
| 41 | <div className="message assistant loading"> | ||
| 42 | <div className="message-content">Thinking...</div> | ||
| 43 | </div> | ||
| 44 | )} | ||
| 45 | <div ref={messagesEndRef} /> | ||
| 46 | </div> | ||
| 47 | |||
| 48 | <div className="chat-input"> | ||
| 49 | <input | ||
| 50 | type="text" | ||
| 51 | value={input} | ||
| 52 | onChange={(e) => setInput(e.target.value)} | ||
| 53 | onKeyDown={(e) => e.key === "Enter" && !e.shiftKey && handleSend()} | ||
| 54 | placeholder={placeholder} | ||
| 55 | disabled={disabled || isLoading} | ||
| 56 | /> | ||
| 57 | <button | ||
| 58 | onClick={handleSend} | ||
| 59 | disabled={disabled || isLoading || !input.trim()} | ||
| 60 | > | ||
| 61 | Send | ||
| 62 | </button> | 47 | </button> |
| 63 | </div> | 48 | </div> |
| 49 | |||
| 50 | {!collapsed && ( | ||
| 51 | <> | ||
| 52 | <div className="chat-messages"> | ||
| 53 | {messages.map((msg) => ( | ||
| 54 | <div key={msg.id} className={`message ${msg.role}`}> | ||
| 55 | <div className="message-content">{msg.content}</div> | ||
| 56 | </div> | ||
| 57 | ))} | ||
| 58 | {isLoading && ( | ||
| 59 | <div className="message assistant loading"> | ||
| 60 | <div className="message-content">Thinking...</div> | ||
| 61 | </div> | ||
| 62 | )} | ||
| 63 | <div ref={messagesEndRef} /> | ||
| 64 | </div> | ||
| 65 | |||
| 66 | <div className="chat-input"> | ||
| 67 | <input | ||
| 68 | type="text" | ||
| 69 | value={input} | ||
| 70 | onChange={(e) => setInput(e.target.value)} | ||
| 71 | onKeyDown={(e) => | ||
| 72 | e.key === "Enter" && !e.shiftKey && handleSend() | ||
| 73 | } | ||
| 74 | placeholder={placeholder} | ||
| 75 | disabled={disabled || isLoading} | ||
| 76 | /> | ||
| 77 | <button | ||
| 78 | onClick={handleSend} | ||
| 79 | disabled={disabled || isLoading || !input.trim()} | ||
| 80 | > | ||
| 81 | Send | ||
| 82 | </button> | ||
| 83 | </div> | ||
| 84 | </> | ||
| 85 | )} | ||
| 64 | </div> | 86 | </div> |
| 65 | ); | 87 | ); |
| 66 | } | 88 | } |
