Add copy button

This commit is contained in:
Nicolas Mowen
2026-02-16 19:20:14 -07:00
parent 730bf3c0b7
commit 76409f79e0
2 changed files with 45 additions and 5 deletions

View File

@@ -127,6 +127,7 @@
"cancel": "Cancel",
"close": "Close",
"copy": "Copy",
"copiedToClipboard": "Copied to clipboard",
"back": "Back",
"history": "History",
"fullscreen": "Fullscreen",

View File

@@ -1,4 +1,14 @@
import ReactMarkdown from "react-markdown";
import { useTranslation } from "react-i18next";
import copy from "copy-to-clipboard";
import { toast } from "sonner";
import { FaCopy } from "react-icons/fa";
import { Button } from "@/components/ui/button";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
type MessageBubbleProps = {
@@ -7,18 +17,47 @@ type MessageBubbleProps = {
};
export function MessageBubble({ role, content }: MessageBubbleProps) {
const { t } = useTranslation(["views/chat", "common"]);
const isUser = role === "user";
const handleCopy = () => {
const text = content?.trim() || "";
if (!text) return;
if (copy(text)) {
toast.success(t("button.copiedToClipboard", { ns: "common" }));
}
};
return (
<div
className={cn(
"rounded-lg px-3 py-2",
isUser
? "self-end bg-primary text-primary-foreground"
: "self-start bg-muted",
"flex flex-col gap-1",
isUser ? "items-end self-end" : "items-start self-start",
)}
>
{isUser ? content : <ReactMarkdown>{content}</ReactMarkdown>}
<div
className={cn(
"rounded-lg px-3 py-2",
isUser ? "bg-primary text-primary-foreground" : "bg-muted",
)}
>
{isUser ? content : <ReactMarkdown>{content}</ReactMarkdown>}
</div>
<Tooltip>
<TooltipTrigger asChild>
<Button
variant="ghost"
size="icon"
className="size-7 text-muted-foreground hover:text-foreground"
onClick={handleCopy}
disabled={!content?.trim()}
aria-label={t("button.copy", { ns: "common" })}
>
<FaCopy className="size-3" />
</Button>
</TooltipTrigger>
<TooltipContent>{t("button.copy", { ns: "common" })}</TooltipContent>
</Tooltip>
</div>
);
}