branch-chat / src /components /MessageBubble.jsx
suvadityamuk's picture
suvadityamuk HF Staff
fix: remove ghost text labels in graph view
7334a07
Raw
History Blame Contribute Delete
2.75 kB
import { useConversation } from '../context/ConversationContext';
import { getChildren } from '../utils/tree';
export default function MessageBubble({ node, onBranch }) {
const { state } = useConversation();
const conv = state.conversations[state.activeConversationId];
const childCount = conv ? getChildren(conv.nodes, node.id).length : 0;
return (
<>
{/* User message */}
<div className="message-row user">
<div className="message-content">
<div className="message-bubble user">{node.userMessage}</div>
<div className="message-actions" style={{ justifyContent: 'flex-end' }}>
{childCount > 1 && (
<span className="branch-count" title={`${childCount} branches`}>
⑂ {childCount}
</span>
)}
<button
className="branch-btn"
onClick={() => onBranch(node)}
title="Create a branch from this point"
>
⑂ Branch
</button>
</div>
</div>
<div className="message-avatar user">U</div>
</div>
{/* Assistant message */}
<div className="message-row assistant">
<div className="message-avatar assistant">AI</div>
<div className="message-content">
<div
className={`message-bubble assistant ${
node.status === 'generating' ? 'generating' : ''
} ${node.status === 'error' ? 'error' : ''}`}
>
{node.status === 'generating' && !node.assistantMessage && (
<span style={{ color: 'var(--text-tertiary)' }}>
<span className="spinner" style={{ marginRight: 8 }} />
Generating…
</span>
)}
{node.status === 'error' && (
<span style={{ color: 'var(--status-error)' }}>
❌ Error generating response
</span>
)}
{node.assistantMessage && (
<span
dangerouslySetInnerHTML={{
__html: formatMessage(node.assistantMessage),
}}
/>
)}
</div>
</div>
</div>
</>
);
}
/**
* Very lightweight markdown-ish formatting.
* Converts **bold**, *italic*, `code`, and newlines.
*/
function formatMessage(text) {
return text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
.replace(/\*(.+?)\*/g, '<em>$1</em>')
.replace(/`([^`]+)`/g, '<code style="background:rgba(255,255,255,0.06);padding:1px 5px;border-radius:3px;font-size:12px;">$1</code>')
.replace(/\n/g, '<br/>');
}