Mirror of https://github.com/roostorg/coop
github.com/roostorg/coop
1import CopyAlt from '@/icons/lni/Web and Technology/copy-alt.svg?react';
2import { Tooltip } from 'antd';
3import { useState } from 'react';
4
5const DEFAULT_TOOLTIP_TEXT = 'Copy to clipboard';
6
7/**
8 * Text component that allows the user to copy the text to their clipboard.
9 */
10export default function CopyTextComponent(props: {
11 // Text to copy to the clipboard
12 value: string;
13 // If value being copied to the clipboard is different from what you'd like
14 // to display to the user, set this value
15 displayValue?: string | JSX.Element;
16 // Tooltip text to display when the user hovers over the text
17 initialTooltipText?: string;
18 // Optional footer items to display below the text
19 footerItems?: JSX.Element[];
20 isError?: boolean;
21 wrapText?: boolean;
22}) {
23 const {
24 value,
25 displayValue = value,
26 initialTooltipText = DEFAULT_TOOLTIP_TEXT,
27 footerItems = [],
28 isError = false,
29 wrapText = false,
30 } = props;
31 const [copyTextTooltipTitle, setCopyTextTooltipTitle] =
32 useState<string>(initialTooltipText);
33
34 const resetTextTooltipTitle = () => {
35 setTimeout(() => setCopyTextTooltipTitle(initialTooltipText), 20);
36 };
37
38 return (
39 <div className="flex flex-col">
40 <Tooltip
41 title={copyTextTooltipTitle}
42 onOpenChange={(visible: boolean) => {
43 if (!visible) {
44 resetTextTooltipTitle();
45 }
46 }}
47 >
48 <div
49 className="flex flex-row items-center cursor-pointer grow"
50 onClick={(event) => {
51 event.preventDefault();
52 event.stopPropagation();
53 navigator.clipboard.writeText(value);
54 setCopyTextTooltipTitle('Copied!');
55 }}
56 >
57 {typeof displayValue === 'string' ? (
58 <span
59 className={`font-normal ${
60 isError ? 'text-red-400' : 'text-slate-400'
61 } ${wrapText ? '' : 'whitespace-nowrap'}`}
62 >
63 {displayValue}
64 </span>
65 ) : (
66 displayValue
67 )}
68 <CopyAlt
69 className={`flex w-4 h-4 min-w-fit ${
70 displayValue && displayValue !== '' ? 'ml-1' : ''
71 } ${isError ? 'fill-red-400' : 'fill-slate-400'}`}
72 />
73 </div>
74 </Tooltip>
75 <div className="flex flex-row">{footerItems}</div>
76 </div>
77 );
78}