1
0

copy-button.tsx 1.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546
  1. 'use client';
  2. import { useState } from 'react';
  3. import { Check, Copy } from 'lucide-react';
  4. import { cn } from '@/lib/cn';
  5. export function CopyButton({
  6. value,
  7. label = 'Copy',
  8. className,
  9. }: {
  10. value: string;
  11. label?: string;
  12. className?: string;
  13. }) {
  14. const [copied, setCopied] = useState(false);
  15. async function copy() {
  16. try {
  17. await navigator.clipboard.writeText(value);
  18. setCopied(true);
  19. setTimeout(() => setCopied(false), 2000);
  20. } catch {
  21. // Clipboard unavailable (insecure context) — ignore.
  22. }
  23. }
  24. return (
  25. <button
  26. type="button"
  27. onClick={copy}
  28. aria-label={copied ? 'Copied' : label}
  29. className={cn(
  30. 'inline-flex items-center gap-1.5 rounded-lg border px-2.5 py-1.5 text-xs font-medium transition-colors hover:bg-fd-accent hover:text-fd-accent-foreground focus-visible:outline-2 focus-visible:outline-fd-ring',
  31. className,
  32. )}
  33. >
  34. {copied ? (
  35. <Check className="size-3.5 text-brand" aria-hidden />
  36. ) : (
  37. <Copy className="size-3.5" aria-hidden />
  38. )}
  39. <span>{copied ? 'Copied' : label}</span>
  40. </button>
  41. );
  42. }