1import { useCopyToClipboard } from "~/hooks/useCopyToClipboard";
2import { cn } from "~/lib/utils";
3
4import { Tooltip, TooltipPopup, TooltipTrigger } from "../ui/tooltip";
5
6export function PullRequestCopyableCode({
7 value,
8 target,
9 copyLabel,
10 copiedLabel,
11 className,
12 tooltipSide = "top",
13 onError,
14}: {
15 readonly value: string;
16 readonly target: string;
17 readonly copyLabel: string;
18 readonly copiedLabel: string;
19 readonly className?: string;
20 readonly tooltipSide?: "top" | "bottom";
21 readonly onError?: (error: Error) => void;
22}) {
23 const { copyToClipboard, isCopied } = useCopyToClipboard({
24 target,
25 timeout: 1600,
26 ...(onError ? { onError } : {}),
27 });
28 return (
29 <Tooltip>
30 <TooltipTrigger
31 render={
32 <button
33 type="button"
34 className={cn(
35 "relative grid w-fit min-w-0 max-w-full shrink cursor-pointer rounded px-1 py-0.5 text-left outline-none transition-colors pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11 hover:bg-accent/45 hover:text-foreground focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-ring focus-visible:ring-offset-1 focus-visible:ring-offset-background",
36 className,
37 )}
38 aria-label={isCopied ? copiedLabel : copyLabel}
39 onClick={() => copyToClipboard(value)}
40 />
41 }
42 >
43 <code
44 className={cn(
45 "col-start-1 row-start-1 min-w-0 truncate transition-opacity duration-150 motion-reduce:transition-none",
46 isCopied ? "opacity-0" : "opacity-100",
47 )}
48 >
49 {value}
50 </code>
51 <span
52 aria-hidden="true"
53 className={cn(
54 "col-start-1 row-start-1 truncate text-center transition-opacity duration-150 motion-reduce:transition-none",
55 isCopied ? "opacity-100" : "opacity-0",
56 )}
57 >
58 Copied
59 </span>
60 </TooltipTrigger>
61 <TooltipPopup variant="code" side={tooltipSide}>
62 {`${isCopied ? "Copied" : copyLabel}: ${value}`}
63 </TooltipPopup>
64 </Tooltip>
65 );
66}