From 94b59fb65f3e6c5049810316c89a225f5cfe9d63 Mon Sep 17 00:00:00 2001 From: Anto01 Date: Thu, 15 Jan 2026 22:45:47 -0500 Subject: [PATCH] feat(canvas): Add message input to ChatPanel with Claude integration - Add textarea input with Enter-to-send functionality to ChatPanel - Pass sendMessage and isConnected props from AtomizerCanvas - Add disabled states during thinking/disconnected states - Use Lucide Send icon for submit button - Show connection status with Sparkles welcome icon Co-Authored-By: Claude Opus 4.5 --- .../src/components/canvas/AtomizerCanvas.tsx | 3 + .../components/canvas/panels/ChatPanel.tsx | 94 ++++++++++++++----- 2 files changed, 74 insertions(+), 23 deletions(-) diff --git a/atomizer-dashboard/frontend/src/components/canvas/AtomizerCanvas.tsx b/atomizer-dashboard/frontend/src/components/canvas/AtomizerCanvas.tsx index f8eb2487..5a02fea9 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/AtomizerCanvas.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/AtomizerCanvas.tsx @@ -47,6 +47,7 @@ function CanvasFlow() { executeIntent, validateIntent, analyzeIntent, + sendMessage, } = useCanvasChat({ onError: (error) => console.error('Canvas chat error:', error), }); @@ -213,6 +214,8 @@ function CanvasFlow() { ) : selectedNode ? ( diff --git a/atomizer-dashboard/frontend/src/components/canvas/panels/ChatPanel.tsx b/atomizer-dashboard/frontend/src/components/canvas/panels/ChatPanel.tsx index 3a9f3ccb..a58634b9 100644 --- a/atomizer-dashboard/frontend/src/components/canvas/panels/ChatPanel.tsx +++ b/atomizer-dashboard/frontend/src/components/canvas/panels/ChatPanel.tsx @@ -1,48 +1,96 @@ /** - * Chat Panel for Canvas - Displays messages from Claude + * Chat Panel for Canvas - Displays messages from Claude with input */ -import { useRef, useEffect } from 'react'; +import { useRef, useEffect, useState, KeyboardEvent } from 'react'; +import { Send, Sparkles } from 'lucide-react'; import { Message, ChatMessage } from '../../chat/ChatMessage'; import { ThinkingIndicator } from '../../chat/ThinkingIndicator'; interface ChatPanelProps { messages: Message[]; isThinking: boolean; + onSendMessage?: (message: string) => void; + isConnected?: boolean; } -export function ChatPanel({ messages, isThinking }: ChatPanelProps) { +export function ChatPanel({ messages, isThinking, onSendMessage, isConnected = true }: ChatPanelProps) { const messagesEndRef = useRef(null); + const [input, setInput] = useState(''); // Auto-scroll to bottom when new messages arrive useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages, isThinking]); + const handleSend = () => { + if (input.trim() && onSendMessage && !isThinking) { + onSendMessage(input.trim()); + setInput(''); + } + }; + + const handleKeyDown = (e: KeyboardEvent) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleSend(); + } + }; + return ( -
- {/* Welcome message if no messages */} - {messages.length === 0 && !isThinking && ( -
-
- 🧠 +
+ {/* Messages */} +
+ {/* Welcome message if no messages */} + {messages.length === 0 && !isThinking && ( +
+
+ +
+

+ Use Validate, Analyze, or Execute to interact with Claude about your optimization workflow. +

+

+ Or type a message below to ask questions. +

+
+ )} + + {/* Messages */} + {messages.map((message) => ( + + ))} + + {/* Thinking indicator */} + {isThinking && } + + {/* Scroll anchor */} +
+
+ + {/* Input */} + {onSendMessage && ( +
+
+