Skip to content

Commit ca88051

Browse files
committed
[MNY-268] Bridge Status UI updates
1 parent 12082fd commit ca88051

File tree

4 files changed

+107
-53
lines changed

4 files changed

+107
-53
lines changed

apps/dashboard/src/@/components/blocks/wallet-address.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ export function WalletAddress(props: {
7878
<HoverCardTrigger asChild tabIndex={-1}>
7979
<Button
8080
className={cn(
81-
"flex flex-row items-center gap-2 px-0",
81+
"flex flex-row items-center gap-2 px-0 max-w-full truncate",
8282
props.className,
8383
)}
8484
onClick={(e) => e.stopPropagation()}
@@ -93,7 +93,7 @@ export function WalletAddress(props: {
9393
fallbackIcon={props.fallbackIcon}
9494
/>
9595
)}
96-
<span className="cursor-pointer font-mono">
96+
<span className="cursor-pointer font-mono max-w-full truncate">
9797
{profiles.data?.[0]?.name || shortenedAddress}
9898
</span>
9999
</Button>

apps/dashboard/src/@/components/ui/CopyTextButton.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function CopyTextButton(props: {
4141
<Button
4242
aria-label={props.tooltip}
4343
className={cn(
44-
"flex h-auto w-auto gap-2 rounded-lg px-1.5 py-0.5 font-normal text-foreground",
44+
"flex h-auto w-auto gap-2 rounded-lg px-1.5 py-0.5 font-normal text-foreground max-w-full truncate",
4545
props.className,
4646
)}
4747
onClick={(e) => {
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
"use client";
2+
import { ArrowUpRightIcon, CheckIcon, CopyIcon } from "lucide-react";
3+
import Link from "next/link";
4+
import { useState } from "react";
5+
import { cn } from "@/lib/utils";
6+
import { Button } from "./button";
7+
import { ToolTipLabel } from "./tooltip";
8+
9+
export function LinkWithCopyButton(props: {
10+
href: string;
11+
textToShow: string;
12+
textToCopy: string;
13+
copyTooltip: string;
14+
className?: string;
15+
}) {
16+
const [isCopied, setIsCopied] = useState(false);
17+
const Icon = isCopied ? CheckIcon : CopyIcon;
18+
19+
return (
20+
<div className={cn("flex items-center gap-1", props.className)}>
21+
<ToolTipLabel label={props.copyTooltip}>
22+
<Button
23+
variant="ghost"
24+
size="sm"
25+
className="p-1 h-auto shrink-0 opacity-70 hover:opacity-100 text-muted-foreground"
26+
onClick={() => {
27+
navigator.clipboard.writeText(props.textToCopy);
28+
setIsCopied(true);
29+
setTimeout(() => setIsCopied(false), 1000);
30+
}}
31+
>
32+
<Icon className="size-3" />
33+
</Button>
34+
</ToolTipLabel>
35+
<Link
36+
href={props.href}
37+
target="_blank"
38+
className="text-sm text-muted-foreground hover:underline flex items-center gap-1 tabular-nums flex-1 truncate hover:text-foreground group"
39+
>
40+
<span className="max-w-full truncate">{props.textToShow}</span>
41+
<ArrowUpRightIcon className="size-3.5 opacity-70 shrink-0 group-hover:opacity-100" />
42+
</Link>
43+
</div>
44+
);
45+
}

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/tx/[txHash]/bridge-status.tsx

Lines changed: 59 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,20 @@ import { useQuery } from "@tanstack/react-query";
33
import { CodeClient } from "@workspace/ui/components/code/code.client";
44
import { Img } from "@workspace/ui/components/img";
55
import { Spinner } from "@workspace/ui/components/spinner";
6-
import { ArrowRightIcon, CircleCheckIcon, CircleXIcon } from "lucide-react";
6+
import {
7+
ArrowRightIcon,
8+
ArrowUpRightIcon,
9+
CircleCheckIcon,
10+
CircleXIcon,
11+
} from "lucide-react";
712
import Link from "next/link";
813
import { NATIVE_TOKEN_ADDRESS, type ThirdwebClient } from "thirdweb";
914
import type { Status, Token } from "thirdweb/bridge";
1015
import { status } from "thirdweb/bridge";
1116
import { toTokens } from "thirdweb/utils";
1217
import { WalletAddress } from "@/components/blocks/wallet-address";
1318
import { CopyTextButton } from "@/components/ui/CopyTextButton";
19+
import { LinkWithCopyButton } from "@/components/ui/link-with-copy-button";
1420
import { SkeletonContainer } from "@/components/ui/skeleton";
1521
import { cn } from "@/lib/utils";
1622
import { fetchChain } from "@/utils/fetchChain";
@@ -46,9 +52,9 @@ export function BridgeStatus(props: {
4652
/>
4753
)}
4854

49-
<div className="px-6 lg:px-8 py-7 space-y-1.5">
50-
<div className="flex justify-between items-center">
51-
<p className="text-sm text-muted-foreground "> Status </p>
55+
<div className="px-6 lg:px-8 py-7 space-y-4">
56+
<div className="space-y-1">
57+
<p className="text-sm text-foreground "> Status </p>
5258

5359
<div
5460
className={cn(
@@ -75,22 +81,23 @@ export function BridgeStatus(props: {
7581
</div>
7682
</div>
7783

78-
<div className="flex justify-between items-center">
79-
<p className="text-sm text-muted-foreground ">Payment ID</p>
84+
<div className="space-y-1">
85+
<p className="text-sm text-foreground ">Payment ID</p>
8086
<CopyTextButton
8187
textToCopy={bridgeStatus.paymentId}
82-
textToShow={`${bridgeStatus.paymentId.slice(0, 6)}...${bridgeStatus.paymentId.slice(-4)}`}
88+
textToShow={bridgeStatus.paymentId}
8389
tooltip="Payment ID"
84-
className="text-sm translate-x-1.5"
90+
className="text-sm -translate-x-1.5 tabular-nums text-muted-foreground"
8591
copyIconPosition="left"
92+
iconClassName="text-muted-foreground/70"
8693
variant="ghost"
8794
/>
8895
</div>
8996
</div>
9097

9198
{purchaseDataString && (
9299
<div className="px-6 lg:px-8 py-7 space-y-2 border-t border-dashed">
93-
<p className="text-sm text-muted-foreground ">Purchase Data</p>
100+
<p className="text-sm text-foreground ">Purchase Data</p>
94101
<CodeClient
95102
code={purchaseDataString}
96103
lang="json"
@@ -113,6 +120,8 @@ function TokenInfo(props: {
113120
txHash: string | undefined;
114121
}) {
115122
const chainQuery = useChainQuery(props.token.chainId);
123+
const isNativeToken =
124+
props.token.address.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase();
116125

117126
return (
118127
<div className="flex-1 pt-10 pb-9 px-6 lg:px-8">
@@ -121,8 +130,9 @@ function TokenInfo(props: {
121130
{props.label}
122131
</h3>
123132
</div>
133+
<div className="h-6" />
124134

125-
<div className="pb-7 pt-6 border-b border-dashed">
135+
<div>
126136
<div className="flex items-center gap-3">
127137
<div className="relative hover:ring-2 hover:ring-offset-2 hover:ring-offset-card hover:ring-foreground/30 rounded-full">
128138
<Link
@@ -178,52 +188,56 @@ function TokenInfo(props: {
178188
render={(data) => (
179189
<Link
180190
href={`/${chainQuery.data?.slug || props.token.chainId}`}
181-
className="text-sm text-muted-foreground leading-none hover:underline"
191+
className="text-sm text-muted-foreground leading-none hover:underline flex items-center gap-1"
182192
target="_blank"
183193
>
184-
{data}
194+
{data}{" "}
195+
<ArrowUpRightIcon className="size-3.5 text-muted-foreground/70 shrink-0" />
185196
</Link>
186197
)}
187198
/>
188199
</div>
189200
</div>
190201
</div>
191202

192-
<div className="h-6" />
203+
<div className="h-8" />
193204

194-
<div className="space-y-1.5">
195-
<div className="flex gap-2.5 justify-between">
196-
<p className="text-sm text-muted-foreground ">{props.addressLabel}</p>
205+
<div className="space-y-4">
206+
<div className="space-y-1">
207+
<p className="text-sm text-foreground ">{props.addressLabel}</p>
197208
<WalletAddress
198209
address={props.walletAddress}
199210
client={props.client}
200-
className="py-0.5 h-auto text-sm [&>*]:!font-sans"
201-
iconClassName="size-3.5"
211+
className="py-0.5 h-auto text-sm [&>*]:!font-sans tabular-nums [&>*]:font-normal text-muted-foreground hover:text-foreground"
212+
iconClassName="size-3"
213+
shortenAddress={false}
202214
/>
203215
</div>
204216

205-
<div className="flex gap-2 justify-between">
206-
<p className="text-sm text-muted-foreground ">Token Address</p>
207-
<CopyTextButton
217+
<div className="space-y-1">
218+
<p className="text-sm text-foreground ">Token Address</p>
219+
<LinkWithCopyButton
220+
href={
221+
isNativeToken
222+
? `/${chainQuery.data?.slug || props.token.chainId}`
223+
: `/${chainQuery.data?.slug || props.token.chainId}/${props.token.address}`
224+
}
225+
textToShow={props.token.address}
208226
textToCopy={props.token.address}
209-
textToShow={`${props.token.address.slice(0, 6)}...${props.token.address.slice(-4)}`}
210-
tooltip="Token Address"
211-
className="text-sm translate-x-1.5"
212-
copyIconPosition="left"
213-
variant="ghost"
227+
copyTooltip="Copy Token Address"
228+
className="-translate-x-1"
214229
/>
215230
</div>
216231

217-
<div className="flex gap-2 justify-between">
218-
<p className="text-sm text-muted-foreground ">Transaction Hash</p>
232+
<div className="space-y-1">
233+
<p className="text-sm text-foreground ">Transaction Hash</p>
219234
{props.txHash ? (
220-
<CopyTextButton
235+
<LinkWithCopyButton
236+
className="-translate-x-1"
237+
href={`/${chainQuery.data?.slug || props.token.chainId}/tx/${props.txHash}`}
238+
textToShow={`${props.txHash.slice(0, 12)}...${props.txHash.slice(-4)}`}
221239
textToCopy={props.txHash}
222-
textToShow={`${props.txHash.slice(0, 6)}...${props.txHash.slice(-4)}`}
223-
tooltip="Transaction Hash"
224-
className="text-sm translate-x-1.5"
225-
copyIconPosition="left"
226-
variant="ghost"
240+
copyTooltip="Copy Transaction Hash"
227241
/>
228242
) : (
229243
<p className="text-sm text-muted-foreground ">N/A</p>
@@ -288,10 +302,8 @@ function FailedBridgeStatusContent(props: {
288302
}) {
289303
return (
290304
<div className="px-6 lg:px-8 py-7 space-y-1.5 border-b border-dashed">
291-
<h3 className="text-base font-medium tracking-tight mb-3">
292-
Transactions
293-
</h3>
294-
<div className="flex flex-col gap-2">
305+
<h3 className="text-lg font-medium tracking-tight mb-4">Transactions</h3>
306+
<div className="space-y-4">
295307
{props.transactions.map((tx) => {
296308
return (
297309
<TxHashRow
@@ -328,34 +340,31 @@ function TxHashRow(props: {
328340
const chainQuery = useChainQuery(props.chainId);
329341

330342
return (
331-
<div className="flex items-center gap-2 justify-between">
343+
<div className="space-y-1">
332344
<div className="flex items-center gap-2">
333345
<Img
334346
src={resolveSchemeWithErrorHandler({
335347
client: props.client,
336348
uri: chainQuery.data?.icon?.url,
337349
})}
338350
alt={chainQuery.data?.name}
339-
className="size-4 rounded-full"
351+
className="size-3.5 rounded-full"
340352
fallback={
341-
<div className="size-4 from-blue-500 to-foreground rounded-full bg-gradient-to-b" />
353+
<div className="size-3.5 from-blue-500 to-foreground rounded-full bg-gradient-to-b" />
342354
}
343355
/>
344356
<SkeletonContainer
345357
skeletonData={`Chain ${props.chainId}`}
346358
loadedData={chainQuery.data?.name}
347-
render={(data) => (
348-
<p className="text-sm text-muted-foreground">{data}</p>
349-
)}
359+
render={(data) => <p className="text-sm text-foreground">{data}</p>}
350360
/>
351361
</div>
352-
<CopyTextButton
362+
<LinkWithCopyButton
363+
href={`/${chainQuery.data?.slug || props.chainId}/tx/${props.txHash}`}
364+
textToShow={props.txHash}
353365
textToCopy={props.txHash}
354-
textToShow={`${props.txHash.slice(0, 6)}...${props.txHash.slice(-4)}`}
355-
tooltip="Copy Transaction Hash"
356-
className="text-sm"
357-
copyIconPosition="right"
358-
variant="ghost"
366+
copyTooltip="Copy Transaction Hash"
367+
className="-translate-x-0.5"
359368
/>
360369
</div>
361370
);

0 commit comments

Comments
 (0)