/ src / frontend / components / CopyTooltip.tsx
CopyTooltip.tsx
  1  // svg
  2  import { ReactComponent as CopyIcon } from "@assets/svg/files/copy-icon.svg";
  3  import { ReactComponent as CopyGrayIcon } from "@/assets/svg/files/copy-gray-icon.svg";
  4  //
  5  import { VariantProps, cva } from "cva";
  6  import { ButtonHTMLAttributes, FC, useState } from "react";
  7  import * as Popover from "@radix-ui/react-popover";
  8  import { useTranslation } from "react-i18next";
  9  
 10  const customCopy = cva("customCopy", {
 11    variants: {
 12      background: {
 13        default: ["bg-AccpetButtonColor"],
 14        noBG: ["bg-transparent"],
 15      },
 16      rounded: {
 17        small: ["rounded-sm"],
 18        medium: ["rounded"],
 19        large: ["rounded-md"],
 20        xLarge: ["rounded-lg"],
 21      },
 22      boxSize: {
 23        none: ["p-0"],
 24        small: ["p-1"],
 25      },
 26    },
 27    defaultVariants: {
 28      boxSize: "none",
 29      background: "noBG",
 30      rounded: "medium",
 31    },
 32  });
 33  
 34  const copyIcon = cva("copyIcon", {
 35    variants: {
 36      size: {
 37        xSmall: ["w-3", "h-3"],
 38        small: ["w-4", "h-4"],
 39        medium: ["w-5", "h-5"],
 40        large: ["w-6", "h-6"],
 41        xLarge: ["w-8", "h-8"],
 42      },
 43    },
 44    defaultVariants: {
 45      size: "medium",
 46    },
 47  });
 48  
 49  export interface TooltipProps
 50    extends ButtonHTMLAttributes<HTMLButtonElement>,
 51      VariantProps<typeof copyIcon>,
 52      VariantProps<typeof customCopy> {
 53    side?: "top" | "right" | "bottom" | "left" | undefined;
 54    sideOffset?: number | undefined;
 55    align?: "center" | "end" | "start" | undefined;
 56    alignOffset?: number | undefined;
 57    showTime?: number | undefined;
 58    copyStroke?: string;
 59    copyText?: string;
 60    isTransaction?: boolean;
 61  }
 62  
 63  export const CustomCopy: FC<TooltipProps> = ({
 64    className,
 65    copyText = "copy",
 66    background,
 67    rounded,
 68    size,
 69    boxSize,
 70    side = "top",
 71    sideOffset = 0,
 72    align = "start",
 73    alignOffset = 0,
 74    showTime = 1000,
 75    copyStroke = "fill-PrimaryTextColorLight dark:fill-PrimaryTextColor",
 76    isTransaction = false,
 77    ...props
 78  }) => {
 79    const { t } = useTranslation();
 80    const [open, setOpen] = useState(false);
 81    return (
 82      <Popover.Root open={open}>
 83        <Popover.Trigger asChild>
 84          <button
 85            onClick={() => {
 86              navigator.clipboard.writeText(copyText);
 87              setOpen(true);
 88              setTimeout(() => {
 89                setOpen(false);
 90              }, showTime);
 91            }}
 92            className={`p-0 ${customCopy({
 93              background,
 94              rounded,
 95              boxSize,
 96              className,
 97            })}`}
 98            {...props}
 99          >
100            {isTransaction ? (
101              <CopyGrayIcon
102                className={`!stroke-0 ${copyStroke} ${copyIcon({ size })}`}
103              />
104            ) : (
105              <CopyIcon
106                className={`!stroke-0 ${copyStroke} ${copyIcon({ size })}`}
107              />
108            )}
109          </button>
110        </Popover.Trigger>
111        <Popover.Portal className="z-[9999]">
112          <Popover.Content
113            className="z-[9999] shadow-md"
114            side={side}
115            sideOffset={sideOffset}
116            align={align}
117            alignOffset={alignOffset}
118          >
119            <div className="flex flex-row justify-start items-center py-1 px-2 bg-SecondaryColorLight/50 dark:bg-SecondaryColor/50 rounded-md">
120              <p className="text-sm text-PrimaryTextColorLight/60 dark:text-PrimaryTextColor/60">
121                {t("copied")}
122              </p>
123            </div>
124            <Popover.Arrow className="fill-SecondaryColorLight/50 dark:fill-SecondaryColor/50" />
125          </Popover.Content>
126        </Popover.Portal>
127      </Popover.Root>
128    );
129  };