valhalla / frontend /src /components /ChatPanel.jsx
Dontcryx_07
final
d660fa9
Raw
History Blame Contribute Delete
1.94 kB
/**
* ChatPanel — read-only live transcript of one agent-to-agent conversation.
*
* Reveals messages one by one to mirror the backend's staged generation,
* and auto-scrolls to the newest message.
*
* Architecture: rendered inside AgentWindow; fed the conversation object
* and the revealed-count from the simulation snapshot.
*
* Design: observation-only — there is deliberately no input to talk to
* agents from the UI.
*/
import { useEffect, useRef } from "react";
import ChatBubble from "./ChatBubble";
export default function ChatPanel({ conversation, selfId, color, revealedCount }) {
const bottomRef = useRef(null);
const messages = conversation?.messages || [];
const visible = revealedCount != null ? messages.slice(0, revealedCount) : messages;
useEffect(() => {
bottomRef.current?.scrollIntoView({ behavior: "smooth" });
}, [visible.length]);
if (!messages.length) return null;
return (
<div style={{
marginTop: 8,
borderTop: "1px solid rgba(212,160,74,0.08)",
paddingTop: 8,
maxHeight: 180,
overflowY: "auto",
}}>
<div style={{
fontSize: 8,
color: "#6b6b78",
marginBottom: 6,
textTransform: "uppercase",
letterSpacing: 1.2,
fontFamily: "'Space Mono', monospace",
}}>
Chat with {conversation.partner_name}
</div>
{visible.map((msg, i) => (
<ChatBubble
key={i}
text={msg.text}
isSelf={msg.speaker === selfId}
color={color}
/>
))}
{revealedCount != null && visible.length < messages.length && (
<div style={{
fontSize: 9,
color: "#6b6b78",
textAlign: "center",
marginTop: 4,
fontStyle: "italic",
fontFamily: "'Space Mono', monospace",
}}>
···
</div>
)}
<div ref={bottomRef} />
</div>
);
}