Highly ambitious ATProtocol AppView service and sdks
at fix-postgres 70 lines 2.0 kB view raw
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}