forked from
slices.network/slices
Highly ambitious ATProtocol AppView service and sdks
1import { useState } from "react";
2import { Copy, Check } from "lucide-react";
3
4interface CopyableFieldProps {
5 value: string;
6 label: string;
7 variant?: "input" | "inline";
8}
9
10export function CopyableField({ value, label, variant = "input" }: CopyableFieldProps) {
11 const [copied, setCopied] = useState(false);
12
13 const handleCopy = async () => {
14 try {
15 await navigator.clipboard.writeText(value);
16 setCopied(true);
17 setTimeout(() => setCopied(false), 2000);
18 } catch (err) {
19 console.error("Failed to copy:", err);
20 }
21 };
22
23 if (variant === "inline") {
24 return (
25 <div className="flex items-center gap-2 group">
26 <span className="text-xs text-zinc-500">{label}:</span>
27 <span className="font-mono text-xs text-zinc-600 break-all">
28 {value}
29 </span>
30 <button
31 type="button"
32 onClick={handleCopy}
33 className="p-1 text-zinc-400 hover:text-zinc-300 transition-colors rounded hover:bg-zinc-700/50 flex-shrink-0 opacity-0 group-hover:opacity-100"
34 title="Copy to clipboard"
35 >
36 {copied ? (
37 <Check size={14} className="text-green-400" />
38 ) : (
39 <Copy size={14} />
40 )}
41 </button>
42 </div>
43 );
44 }
45
46 return (
47 <div>
48 <label className="text-xs text-zinc-500 block mb-1">
49 {label}
50 </label>
51 <div className="relative">
52 <div className="bg-zinc-800/50 border border-zinc-700 rounded px-3 py-2 pr-10 font-mono text-sm text-zinc-300 break-all">
53 {value}
54 </div>
55 <button
56 type="button"
57 onClick={handleCopy}
58 className="absolute right-2 top-1/2 -translate-y-1/2 p-1.5 text-zinc-400 hover:text-zinc-300 transition-colors rounded hover:bg-zinc-700/50"
59 title="Copy to clipboard"
60 >
61 {copied ? (
62 <Check size={16} className="text-green-400" />
63 ) : (
64 <Copy size={16} />
65 )}
66 </button>
67 </div>
68 </div>
69 );
70}