Merge pull request 'Copy button + hover highlight on assistant messages' (#41) from copy-answer-messages into main

Reviewed-on: #41
This commit was merged in pull request #41.
This commit is contained in:
2026-09-11 16:28:52 -04:00
+26 -3
View File
@@ -1,6 +1,7 @@
import React from "react";
import { useState } from "react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { Copy, Check } from "lucide-react";
type AnswerBubbleProps = {
text: string;
@@ -8,6 +9,19 @@ type AnswerBubbleProps = {
};
export const AnswerBubble = React.memo(({ text, loading }: AnswerBubbleProps) => {
const [copied, setCopied] = useState(false);
const handleCopy = async (event: React.MouseEvent) => {
event.stopPropagation();
try {
await navigator.clipboard.writeText(text);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
// Clipboard unavailable (e.g. insecure context) — ignore
}
};
return (
<div className="message-enter">
{loading ? (
@@ -17,8 +31,17 @@ export const AnswerBubble = React.memo(({ text, loading }: AnswerBubbleProps) =>
<span className="loading-dot w-2 h-2 rounded-full bg-amber-soft inline-block" />
</div>
) : (
<div className="markdown-content text-[15px] leading-relaxed text-charcoal">
<ReactMarkdown remarkPlugins={[remarkGfm]}>{text}</ReactMarkdown>
<div className="group relative -mx-3 -my-2 rounded-xl px-3 py-2 transition-colors duration-150 hover:bg-amber-soft/10">
<div className="markdown-content text-[15px] leading-relaxed text-charcoal">
<ReactMarkdown remarkPlugins={[remarkGfm]}>{text}</ReactMarkdown>
</div>
<button
onClick={handleCopy}
aria-label={copied ? "Copied" : "Copy message"}
className="absolute top-0 right-0 flex h-7 w-7 items-center justify-center rounded-lg border border-sand-light/60 bg-warm-white text-warm-gray shadow-sm opacity-0 transition-opacity duration-150 group-hover:opacity-100 hover:text-charcoal hover:bg-cream-dark focus:opacity-100 focus:outline-none cursor-pointer"
>
{copied ? <Check size={14} className="text-green-600" /> : <Copy size={14} />}
</button>
</div>
)}
</div>