Skip to content

Instantly share code, notes, and snippets.

@yinkakun
Created November 15, 2023 10:35
Show Gist options
  • Save yinkakun/104a816d27874942f74a89f59dd95012 to your computer and use it in GitHub Desktop.
Save yinkakun/104a816d27874942f74a89f59dd95012 to your computer and use it in GitHub Desktop.
import React from "react";
import { cn } from "lib/utils";
import { useCopyToClipboard } from "usehooks-ts";
import { Check, Copy, EyeOff } from "lucide-react";
export interface CopyToClipboardProps {
value: string;
secret?: boolean;
className?: string;
}
export const CopyToClipboard: React.FC<CopyToClipboardProps> = ({
value,
secret,
className,
}) => {
const [_, setCopiedText] = useCopyToClipboard();
const [copied, setCopied] = React.useState(false);
const [reveal, setReveal] = React.useState(false);
const copy = () => {
setCopiedText(value);
setCopied(true);
setTimeout(() => {
setReveal(false);
setCopied(false);
}, 5000);
};
return (
<div className={cn("relative w-full", className)}>
<input
value={reveal ? value : secret ? redacted() : value}
readOnly
className={cn(
"w-full border outline-none rounded-lg leading-none px-3 py-2 bg-white border-[#AED2BC] hover:bg-primary hover:bg-opacity-5 duration-200"
)}
/>
<div className="absolute top-1/2 -translate-y-1/2 right-2">
{!secret && (
<button
onClick={copy}
className="text-primary rounded-md px-3 bg-green-50 border border-primary p-1 duration-200 flex items-center text-xs gap-2"
>
{copied ? (
<React.Fragment>
<span>Copied</span>
<Check size={14} />
</React.Fragment>
) : (
<React.Fragment>
<span>Copy</span>
<Copy size={14} />
</React.Fragment>
)}
</button>
)}
{secret && (
<div>
{reveal ? (
<button
onClick={copy}
className="text-primary rounded-md px-3 bg-green-50 border border-primary p-1 duration-200 flex items-center text-xs gap-2"
>
{copied ? (
<React.Fragment>
<span>Copied</span>
<Check size={14} />
</React.Fragment>
) : (
<React.Fragment>
<span>Copy</span>
<Copy size={14} />
</React.Fragment>
)}
</button>
) : (
<button
onClick={() => {
setReveal(true);
}}
className="text-primary rounded-md px-3 bg-green-50 border border-primary p-1 duration-200 flex items-center text-xs gap-2"
>
<span>Reveal</span>
<EyeOff size={14} />
</button>
)}
</div>
)}
</div>
</div>
);
};
const redacted = () => {
return "******* ******* ******* *******";
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment