fix: move action buttons below content to prevent overlap on short messages (v1.63.4)
This commit is contained in:
@@ -501,13 +501,58 @@ export const ChatMessageComponent = memo(function ChatMessageComponent({ message
|
|||||||
|
|
||||||
{/* Bubble */}
|
{/* Bubble */}
|
||||||
<div className={`min-w-0 max-w-[80%] ${isUser ? 'text-right' : ''}`}>
|
<div className={`min-w-0 max-w-[80%] ${isUser ? 'text-right' : ''}`}>
|
||||||
<div className={`group relative inline-block text-left rounded-3xl px-4 py-3 text-sm leading-relaxed max-w-full min-w-[8rem] overflow-hidden ${
|
<div className={`group relative inline-block text-left rounded-3xl px-4 py-3 text-sm leading-relaxed max-w-full overflow-hidden ${
|
||||||
isUser
|
isUser
|
||||||
? (isLight
|
? (isLight
|
||||||
? 'bg-[rgba(var(--pc-accent-rgb),0.12)] text-pc-text border border-[rgba(var(--pc-accent-rgb),0.3)]'
|
? 'bg-[rgba(var(--pc-accent-rgb),0.12)] text-pc-text border border-[rgba(var(--pc-accent-rgb),0.3)]'
|
||||||
: 'bg-[rgba(var(--pc-accent-rgb),0.08)] text-pc-text border border-[rgba(var(--pc-accent-rgb),0.2)]')
|
: 'bg-[rgba(var(--pc-accent-rgb),0.08)] text-pc-text border border-[rgba(var(--pc-accent-rgb),0.2)]')
|
||||||
: 'bg-pc-elevated/40 text-pc-text border border-pc-border shadow-[0_0_0_1px_rgba(255,255,255,0.03)]'
|
: 'bg-pc-elevated/40 text-pc-text border border-pc-border shadow-[0_0_0_1px_rgba(255,255,255,0.03)]'
|
||||||
}`}>
|
}`}>
|
||||||
|
{/* User-visible text */}
|
||||||
|
{!isUser ? (
|
||||||
|
<CollapsibleContent content={message.content || ''} isStreaming={message.isStreaming}>
|
||||||
|
{message.blocks.length > 0 ? renderTextBlocks(message.blocks) : (
|
||||||
|
<div className="markdown-body">
|
||||||
|
<LazyMarkdown components={markdownComponents}>
|
||||||
|
{autoFormatText(message.content)}
|
||||||
|
</LazyMarkdown>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</CollapsibleContent>
|
||||||
|
) : (
|
||||||
|
message.blocks.length > 0 ? renderTextBlocks(message.blocks) : (
|
||||||
|
<div className="markdown-body">
|
||||||
|
<LazyMarkdown components={markdownComponents}>
|
||||||
|
{autoFormatText(message.content)}
|
||||||
|
</LazyMarkdown>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Inline images */}
|
||||||
|
{renderImageBlocks(message.blocks)}
|
||||||
|
|
||||||
|
{/* Streaming indicator */}
|
||||||
|
{message.isStreaming && (() => {
|
||||||
|
const hasVisibleContent = message.content?.trim();
|
||||||
|
if (!hasVisibleContent) {
|
||||||
|
return <ThinkingIndicator />;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="flex gap-1 mt-2">
|
||||||
|
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
||||||
|
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
||||||
|
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})()}
|
||||||
|
|
||||||
|
{/* Tool calls & thinking (inline) */}
|
||||||
|
{!isUser && <InternalsSummary blocks={message.blocks} />}
|
||||||
|
|
||||||
|
{/* Raw JSON viewer */}
|
||||||
|
{showRawJson && <RawJsonPanel message={rawMessage} />}
|
||||||
|
|
||||||
{/* Action buttons — bottom-right toolbar, inside the bubble */}
|
{/* Action buttons — bottom-right toolbar, inside the bubble */}
|
||||||
<div className={`flex flex-nowrap gap-0.5 justify-end mt-1.5 -mb-1 opacity-0 group-hover:opacity-100 transition-all`}>
|
<div className={`flex flex-nowrap gap-0.5 justify-end mt-1.5 -mb-1 opacity-0 group-hover:opacity-100 transition-all`}>
|
||||||
{!isUser && !message.isStreaming && getPlainText(message).trim() && (
|
{!isUser && !message.isStreaming && getPlainText(message).trim() && (
|
||||||
@@ -553,51 +598,6 @@ export const ChatMessageComponent = memo(function ChatMessageComponent({ message
|
|||||||
<MetadataViewer metadata={message.metadata} />
|
<MetadataViewer metadata={message.metadata} />
|
||||||
<RawJsonToggle isOpen={showRawJson} onToggle={() => setShowRawJson(o => !o)} />
|
<RawJsonToggle isOpen={showRawJson} onToggle={() => setShowRawJson(o => !o)} />
|
||||||
</div>
|
</div>
|
||||||
{/* Retry button moved into the action toolbar below */}
|
|
||||||
{/* User-visible text */}
|
|
||||||
{!isUser ? (
|
|
||||||
<CollapsibleContent content={message.content || ''} isStreaming={message.isStreaming}>
|
|
||||||
{message.blocks.length > 0 ? renderTextBlocks(message.blocks) : (
|
|
||||||
<div className="markdown-body">
|
|
||||||
<LazyMarkdown components={markdownComponents}>
|
|
||||||
{autoFormatText(message.content)}
|
|
||||||
</LazyMarkdown>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CollapsibleContent>
|
|
||||||
) : (
|
|
||||||
message.blocks.length > 0 ? renderTextBlocks(message.blocks) : (
|
|
||||||
<div className="markdown-body">
|
|
||||||
<LazyMarkdown components={markdownComponents}>
|
|
||||||
{autoFormatText(message.content)}
|
|
||||||
</LazyMarkdown>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Inline images */}
|
|
||||||
{renderImageBlocks(message.blocks)}
|
|
||||||
|
|
||||||
{/* Streaming indicator */}
|
|
||||||
{message.isStreaming && (() => {
|
|
||||||
const hasVisibleContent = message.content?.trim();
|
|
||||||
if (!hasVisibleContent) {
|
|
||||||
return <ThinkingIndicator />;
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<div className="flex gap-1 mt-2">
|
|
||||||
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
|
||||||
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
|
||||||
<span className="bounce-dot w-1.5 h-1.5 rounded-full bg-gradient-to-r from-cyan-300/80 to-violet-400/80 inline-block" />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
})()}
|
|
||||||
|
|
||||||
{/* Tool calls & thinking (inline) */}
|
|
||||||
{!isUser && <InternalsSummary blocks={message.blocks} />}
|
|
||||||
|
|
||||||
{/* Raw JSON viewer */}
|
|
||||||
{showRawJson && <RawJsonPanel message={rawMessage} />}
|
|
||||||
</div>
|
</div>
|
||||||
{(message.timestamp || wasWebhookMessage || isBookmarked) && (
|
{(message.timestamp || wasWebhookMessage || isBookmarked) && (
|
||||||
<div className={`mt-1 flex items-center gap-1.5 text-[11px] text-pc-text-muted ${isUser ? 'justify-end pr-2' : 'pl-2'}`}>
|
<div className={`mt-1 flex items-center gap-1.5 text-[11px] text-pc-text-muted ${isUser ? 'justify-end pr-2' : 'pl-2'}`}>
|
||||||
|
|||||||
Reference in New Issue
Block a user