diff --git a/apps/dashboard/src/@/components/blocks/wallet-address.stories.tsx b/apps/dashboard/src/@/components/blocks/wallet-address.stories.tsx new file mode 100644 index 00000000000..0612e077e18 --- /dev/null +++ b/apps/dashboard/src/@/components/blocks/wallet-address.stories.tsx @@ -0,0 +1,120 @@ +import type { Meta, StoryObj } from "@storybook/nextjs"; +import { type ThirdwebClient, ZERO_ADDRESS } from "thirdweb"; +import type { SocialProfile } from "thirdweb/react"; +import { BadgeContainer, storybookThirdwebClient } from "@/storybook/utils"; +import { WalletAddress, WalletAddressUI } from "./wallet-address"; + +const meta = { + component: Story, + parameters: { + nextjs: { + appDirectory: true, + }, + }, + title: "blocks/WalletAddress", +} satisfies Meta; + +export default meta; +type Story = StoryObj; + +export const Variants: Story = { + args: {}, +}; + +function Story() { + const client = storybookThirdwebClient as unknown as ThirdwebClient; + + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + +
+ ); +} + +const vitalikEth: SocialProfile[] = [ + { + type: "ens", + name: "vitalik.eth", + bio: "mi pinxe lo crino tcati", + avatar: "https://euc.li/vitalik.eth", + metadata: { + name: "vitalik.eth", + address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + avatar: "https://euc.li/vitalik.eth", + description: "mi pinxe lo crino tcati", + url: "https://vitalik.ca", + }, + }, + { + type: "farcaster", + name: "vitalik.eth", + bio: undefined, + avatar: + "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/b663cd63-fecf-4d0f-7f87-0e0b6fd42800/original", + metadata: { + fid: 5650, + bio: undefined, + pfp: "https://imagedelivery.net/BXluQx4ige9GuW0Ia56BHw/b663cd63-fecf-4d0f-7f87-0e0b6fd42800/original", + username: "vitalik.eth", + addresses: [ + "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + "0x96B6bB2bd2Eba3b4Fbefd7DbAC448ad7B6CBf279", + ], + }, + }, +]; diff --git a/apps/dashboard/src/@/components/blocks/wallet-address.tsx b/apps/dashboard/src/@/components/blocks/wallet-address.tsx index c7905aeaf2c..82db53e6476 100644 --- a/apps/dashboard/src/@/components/blocks/wallet-address.tsx +++ b/apps/dashboard/src/@/components/blocks/wallet-address.tsx @@ -1,11 +1,10 @@ "use client"; -import { CheckIcon, CircleSlashIcon, CopyIcon, XIcon } from "lucide-react"; +import { CircleSlashIcon, XIcon } from "lucide-react"; import { useMemo } from "react"; import { isAddress, type ThirdwebClient, ZERO_ADDRESS } from "thirdweb"; import { Blobbie, type SocialProfile, useSocialProfiles } from "thirdweb/react"; import { Img } from "@/components/blocks/Img"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { HoverCard, @@ -13,22 +12,49 @@ import { HoverCardTrigger, } from "@/components/ui/hover-card"; import { ToolTipLabel } from "@/components/ui/tooltip"; -import { useClipboard } from "@/hooks/useClipboard"; import { cn } from "@/lib/utils"; import { resolveSchemeWithErrorHandler } from "@/utils/resolveSchemeWithErrorHandler"; +import { CopyTextButton } from "../ui/CopyTextButton"; +import { Skeleton } from "../ui/skeleton"; -export function WalletAddress(props: { +type WalletAddressProps = { address: string | undefined; shortenAddress?: boolean; className?: string; iconClassName?: string; client: ThirdwebClient; fallbackIcon?: React.ReactNode; -}) { +}; + +export function WalletAddress(props: WalletAddressProps) { + const profiles = useSocialProfiles({ + address: props.address, + client: props.client, + }); + + return ( + + ); +} + +export function WalletAddressUI( + props: WalletAddressProps & { + profiles: { + data: SocialProfile[]; + isPending: boolean; + }; + }, +) { // default back to zero address if no address provided const address = useMemo(() => props.address || ZERO_ADDRESS, [props.address]); - const [shortenedAddress, lessShortenedAddress] = useMemo(() => { + const [shortenedAddress, _lessShortenedAddress] = useMemo(() => { return [ props.shortenAddress !== false ? `${address.slice(0, 6)}...${address.slice(-4)}` @@ -37,17 +63,10 @@ export function WalletAddress(props: { ]; }, [address, props.shortenAddress]); - const profiles = useSocialProfiles({ - address: address, - client: props.client, - }); - - const { onCopy, hasCopied } = useClipboard(address, 2000); - if (!isAddress(address)) { return ( - +
@@ -88,89 +107,82 @@ export function WalletAddress(props: { )} - {profiles.data?.[0]?.name || shortenedAddress} + {props.profiles.data?.[0]?.name || shortenedAddress} { // do not close the hover card when clicking anywhere in the content e.stopPropagation(); }} >
-
-

Wallet Address

- +
+

Wallet Address

+ +
-

- {lessShortenedAddress} -

-

Social Profiles

- {profiles.isPending ? ( -

Loading profiles...

- ) : !profiles.data?.length ? ( -

No profiles found

- ) : ( - profiles.data?.map((profile) => { - const walletAvatarLink = resolveSchemeWithErrorHandler({ - client: props.client, - uri: profile.avatar, - }); - - return ( -
- {walletAvatarLink && ( - - - {profile.name && ( - - {profile.name.slice(0, 2)} - - )} - - )} -
-
-

{profile.name}

- {profile.type} + +
+

Social Profiles

+ + {props.profiles.isPending ? ( + + ) : !props.profiles.data?.length ? ( +

No profiles found

+ ) : ( +
+ {props.profiles.data?.map((profile) => { + const walletAvatarLink = resolveSchemeWithErrorHandler({ + client: props.client, + uri: profile.avatar, + }); + + return ( +
+ + + {profile.name && ( + + {profile.name.slice(0, 2)} + + )} + + +
+

{profile.name}

+ + {profile.type === "ens" ? "ENS" : profile.type} + +
- {profile.bio && ( -

- {profile.bio} -

- )} -
-
- ); - }) - )} + ); + })} +
+ )} +
diff --git a/packages/thirdweb/src/react/core/social/useSocialProfiles.ts b/packages/thirdweb/src/react/core/social/useSocialProfiles.ts index e88b7d8823d..4a623efb44b 100644 --- a/packages/thirdweb/src/react/core/social/useSocialProfiles.ts +++ b/packages/thirdweb/src/react/core/social/useSocialProfiles.ts @@ -37,6 +37,6 @@ export function useSocialProfiles(options: { return await getSocialProfiles({ address, client }); }, queryKey: ["social-profiles", address], - retry: 3, + retry: false, }); }