Open History to see the last commit
1import { memo, useRef } from "react";
2import { CheckIcon, CopyIcon, type LucideIcon } from "lucide-react";
3import { Button } from "../ui/button";
4import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
5import {
6 ANCHORED_COPY_TOAST_TIMEOUT_MS,
7 showAnchoredCopyErrorToast,
8 showAnchoredCopySuccessToast,
9} from "../ui/anchoredCopyToast";
10import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
11
12export const MessageCopyButton = memo(function MessageCopyButton({
13 text,
14 label = "Copy message",
15 icon: Icon = CopyIcon,
16 extraFlavors,
17 size = "xs",
18 variant = "outline",
19 className,
20}: {
21 text: string;
22 label?: string;
23 icon?: LucideIcon;
24 extraFlavors?: Readonly<Record<string, string>>;
25 size?: "xs" | "icon-xs";
26 variant?: "outline" | "ghost";
27 className?: string;
28}) {
29 const ref = useRef<HTMLButtonElement>(null);
30 const { copyToClipboard, isCopied } = useCopyToClipboard<void>({
31 onCopy: () => showAnchoredCopySuccessToast(ref),
32 onError: (error: Error) => showAnchoredCopyErrorToast(ref, error),
33 timeout: ANCHORED_COPY_TOAST_TIMEOUT_MS,
34 ...(extraFlavors ? { extraFlavors } : {}),
35 });
36
37 return (
38 <Tooltip>
39 <TooltipTrigger
40 render={
41 <Button
42 aria-label={label}
43 disabled={isCopied}
44 onClick={() => copyToClipboard(text)}
45 ref={ref}
46 type="button"
47 size={size}
48 variant={variant === "ghost" ? "ghost-muted" : variant}
49 className={className}
50 />
51 }
52 >
53 {isCopied ? <CheckIcon className="size-3 text-primary" /> : <Icon className="size-3" />}
54 </TooltipTrigger>
55 <TooltipPopup>
56 <p>{label}</p>
57 </TooltipPopup>
58 </Tooltip>
59 );
60});