From b1b9cb7a20108ab998d892d814a8f0eac6c3674f Mon Sep 17 00:00:00 2001 From: tusharshah21 Date: Sun, 5 Oct 2025 13:37:55 +0530 Subject: [PATCH] feat: Add copy to clipboard icons next to all ethereum addresses --- .../src/components/CopyAddressToClipboard.tsx | 64 +++++++++++++++++++ .../components/profiles/list/ProfileCard.tsx | 10 ++- .../profile-page/ProfileAttestations.tsx | 14 ++-- .../profiles/profile-page/ProfileHeader.tsx | 8 ++- 4 files changed, 89 insertions(+), 7 deletions(-) create mode 100644 frontend/src/components/CopyAddressToClipboard.tsx diff --git a/frontend/src/components/CopyAddressToClipboard.tsx b/frontend/src/components/CopyAddressToClipboard.tsx new file mode 100644 index 0000000..1f314a5 --- /dev/null +++ b/frontend/src/components/CopyAddressToClipboard.tsx @@ -0,0 +1,64 @@ +import { useState } from "react"; +import { Copy, Check } from "lucide-react"; +import { cn } from "@/lib/utils"; + +interface CopyAddressToClipboardProps { + address: string; + displayAddress?: string; + className?: string; + iconSize?: "sm" | "md"; + showFeedback?: boolean; +} + +export function CopyAddressToClipboard({ + address, + displayAddress, + className, + iconSize = "sm", + showFeedback = true, +}: CopyAddressToClipboardProps) { + const [copied, setCopied] = useState(false); + + const handleCopy = async (e: React.MouseEvent) => { + e.preventDefault(); + e.stopPropagation(); + + try { + await navigator.clipboard.writeText(address); + if (showFeedback) { + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } + } catch (err) { + console.error("Failed to copy address:", err); + } + }; + + const iconClasses = cn( + "transition-colors hover:text-gray-700 cursor-pointer", + iconSize === "sm" ? "h-3.5 w-3.5" : "h-4 w-4", + copied ? "text-green-600" : "text-gray-500" + ); + + return ( +
+ {displayAddress && ( + {displayAddress} + )} + +
+ ); +} + +export default CopyAddressToClipboard; diff --git a/frontend/src/components/profiles/list/ProfileCard.tsx b/frontend/src/components/profiles/list/ProfileCard.tsx index eae0318..f3c590a 100644 --- a/frontend/src/components/profiles/list/ProfileCard.tsx +++ b/frontend/src/components/profiles/list/ProfileCard.tsx @@ -12,6 +12,7 @@ import { useAccount } from "wagmi"; import DeleteProfileDialog from "../action-buttons/DeleteProfileDialog"; import { AddAttestationDialog } from "../action-buttons/AddAttestationDialog"; import AddressTokenBalance from "@/components/AddressTokenBalance"; +import CopyAddressToClipboard from "@/components/CopyAddressToClipboard"; interface ProfileCardProps { address: string; @@ -75,10 +76,15 @@ export function ProfileCard({ )} - - + + {displayAddress} + diff --git a/frontend/src/components/profiles/profile-page/ProfileAttestations.tsx b/frontend/src/components/profiles/profile-page/ProfileAttestations.tsx index e9fae57..2ed7742 100644 --- a/frontend/src/components/profiles/profile-page/ProfileAttestations.tsx +++ b/frontend/src/components/profiles/profile-page/ProfileAttestations.tsx @@ -8,6 +8,7 @@ import { AccordionTrigger, } from "@/components/ui/accordion"; import { useGetProfiles } from "@/hooks/profiles/use-get-profiles"; +import CopyAddressToClipboard from "@/components/CopyAddressToClipboard"; export function ProfileAttestations({ address }: { address: string }) { const attestationsQuery = useGetAttestations(); @@ -87,17 +88,22 @@ export function ProfileAttestations({ address }: { address: string }) {

{it.justification}

-

- Issued by{" "} +

+ Issued by{" "} {profileNameByAddress.get( it.issuer.toLowerCase() - ) || it.issuer} + ) || `${it.issuer.slice(0, 6)}...${it.issuer.slice(-4)}`} -

+ +
diff --git a/frontend/src/components/profiles/profile-page/ProfileHeader.tsx b/frontend/src/components/profiles/profile-page/ProfileHeader.tsx index cd0bc07..f75916a 100644 --- a/frontend/src/components/profiles/profile-page/ProfileHeader.tsx +++ b/frontend/src/components/profiles/profile-page/ProfileHeader.tsx @@ -3,6 +3,7 @@ import { useAccount } from "wagmi"; import { useMemo } from "react"; import { useGetProfiles } from "@/hooks/profiles/use-get-profiles"; import AddressTokenBalance from "@/components/AddressTokenBalance"; +import CopyAddressToClipboard from "@/components/CopyAddressToClipboard"; export function ProfileHeader({ address }: { address: string }) { const profilesQuery = useGetProfiles(); @@ -43,7 +44,12 @@ export function ProfileHeader({ address }: { address: string }) { )} {displayAddress ? ( -

{displayAddress}

+ ) : null}