-
Notifications
You must be signed in to change notification settings - Fork 617
[MNY-268] Bridge Status UI updates #8273
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,45 @@ | ||||||||||||||||||
| "use client"; | ||||||||||||||||||
| import { ArrowUpRightIcon, CheckIcon, CopyIcon } from "lucide-react"; | ||||||||||||||||||
| import Link from "next/link"; | ||||||||||||||||||
| import { useState } from "react"; | ||||||||||||||||||
| import { cn } from "@/lib/utils"; | ||||||||||||||||||
| import { Button } from "./button"; | ||||||||||||||||||
| import { ToolTipLabel } from "./tooltip"; | ||||||||||||||||||
|
|
||||||||||||||||||
| export function LinkWithCopyButton(props: { | ||||||||||||||||||
| href: string; | ||||||||||||||||||
| textToShow: string; | ||||||||||||||||||
| textToCopy: string; | ||||||||||||||||||
| copyTooltip: string; | ||||||||||||||||||
| className?: string; | ||||||||||||||||||
| }) { | ||||||||||||||||||
MananTank marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
| const [isCopied, setIsCopied] = useState(false); | ||||||||||||||||||
| const Icon = isCopied ? CheckIcon : CopyIcon; | ||||||||||||||||||
MananTank marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
|
|
||||||||||||||||||
| return ( | ||||||||||||||||||
| <div className={cn("flex items-center gap-1", props.className)}> | ||||||||||||||||||
| <ToolTipLabel label={props.copyTooltip}> | ||||||||||||||||||
| <Button | ||||||||||||||||||
| variant="ghost" | ||||||||||||||||||
| size="sm" | ||||||||||||||||||
| className="p-1 h-auto shrink-0 opacity-70 hover:opacity-100 text-muted-foreground" | ||||||||||||||||||
| onClick={() => { | ||||||||||||||||||
| navigator.clipboard.writeText(props.textToCopy); | ||||||||||||||||||
| setIsCopied(true); | ||||||||||||||||||
| setTimeout(() => setIsCopied(false), 1000); | ||||||||||||||||||
| }} | ||||||||||||||||||
| > | ||||||||||||||||||
| <Icon className="size-3" /> | ||||||||||||||||||
| </Button> | ||||||||||||||||||
| </ToolTipLabel> | ||||||||||||||||||
| <Link | ||||||||||||||||||
| href={props.href} | ||||||||||||||||||
| target="_blank" | ||||||||||||||||||
| className="text-sm text-muted-foreground hover:underline flex items-center gap-1 tabular-nums flex-1 truncate hover:text-foreground group" | ||||||||||||||||||
| > | ||||||||||||||||||
| <span className="max-w-full truncate">{props.textToShow}</span> | ||||||||||||||||||
| <ArrowUpRightIcon className="size-3.5 opacity-70 shrink-0 group-hover:opacity-100" /> | ||||||||||||||||||
|
Comment on lines
+38
to
+41
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not truncate; wrap long hashes/addresses. This component truncates by default, violating MNY-268. Allow wrapping with break-all; remove truncate classes. - className="text-sm text-muted-foreground hover:underline flex items-center gap-1 tabular-nums flex-1 truncate hover:text-foreground group"
+ className="text-sm text-muted-foreground hover:underline flex items-center gap-1 tabular-nums flex-1 break-all hover:text-foreground group"
@@
- <span className="max-w-full truncate">{props.textToShow}</span>
+ <span className="max-w-full break-all">{props.textToShow}</span>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
| </Link> | ||||||||||||||||||
| </div> | ||||||||||||||||||
| ); | ||||||||||||||||||
| } | ||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,14 +3,20 @@ import { useQuery } from "@tanstack/react-query"; | |
| import { CodeClient } from "@workspace/ui/components/code/code.client"; | ||
| import { Img } from "@workspace/ui/components/img"; | ||
| import { Spinner } from "@workspace/ui/components/spinner"; | ||
| import { ArrowRightIcon, CircleCheckIcon, CircleXIcon } from "lucide-react"; | ||
| import { | ||
| ArrowRightIcon, | ||
| ArrowUpRightIcon, | ||
| CircleCheckIcon, | ||
| CircleXIcon, | ||
| } from "lucide-react"; | ||
| import Link from "next/link"; | ||
| import { NATIVE_TOKEN_ADDRESS, type ThirdwebClient } from "thirdweb"; | ||
| import type { Status, Token } from "thirdweb/bridge"; | ||
| import { status } from "thirdweb/bridge"; | ||
| import { toTokens } from "thirdweb/utils"; | ||
| import { WalletAddress } from "@/components/blocks/wallet-address"; | ||
| import { CopyTextButton } from "@/components/ui/CopyTextButton"; | ||
| import { LinkWithCopyButton } from "@/components/ui/link-with-copy-button"; | ||
| import { SkeletonContainer } from "@/components/ui/skeleton"; | ||
| import { cn } from "@/lib/utils"; | ||
| import { fetchChain } from "@/utils/fetchChain"; | ||
|
|
@@ -46,9 +52,9 @@ export function BridgeStatus(props: { | |
| /> | ||
| )} | ||
|
|
||
| <div className="px-6 lg:px-8 py-7 space-y-1.5"> | ||
| <div className="flex justify-between items-center"> | ||
| <p className="text-sm text-muted-foreground "> Status </p> | ||
| <div className="px-6 lg:px-8 py-7 space-y-4"> | ||
| <div className="space-y-1"> | ||
| <p className="text-sm text-foreground "> Status </p> | ||
|
|
||
| <div | ||
| className={cn( | ||
|
|
@@ -75,22 +81,23 @@ export function BridgeStatus(props: { | |
| </div> | ||
| </div> | ||
|
|
||
| <div className="flex justify-between items-center"> | ||
| <p className="text-sm text-muted-foreground ">Payment ID</p> | ||
| <div className="space-y-1"> | ||
| <p className="text-sm text-foreground ">Payment ID</p> | ||
| <CopyTextButton | ||
| textToCopy={bridgeStatus.paymentId} | ||
| textToShow={`${bridgeStatus.paymentId.slice(0, 6)}...${bridgeStatus.paymentId.slice(-4)}`} | ||
| textToShow={bridgeStatus.paymentId} | ||
| tooltip="Payment ID" | ||
| className="text-sm translate-x-1.5" | ||
| className="text-sm -translate-x-1.5 tabular-nums text-muted-foreground" | ||
| copyIconPosition="left" | ||
| iconClassName="text-muted-foreground/70" | ||
| variant="ghost" | ||
| /> | ||
| </div> | ||
|
Comment on lines
+84
to
95
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Payment ID must not truncate. As implemented, CopyTextButton applies truncation internally; ensure the full Payment ID is visible per MNY-268. Quick fix here: override truncation via className. - <CopyTextButton
+ <CopyTextButton
textToCopy={bridgeStatus.paymentId}
textToShow={bridgeStatus.paymentId}
tooltip="Payment ID"
- className="text-sm -translate-x-1.5 tabular-nums text-muted-foreground"
+ className="text-sm -translate-x-1.5 tabular-nums text-muted-foreground whitespace-normal break-all overflow-visible"
copyIconPosition="left"
iconClassName="text-muted-foreground/70"
variant="ghost"
/>Preferably also remove truncate in CopyTextButton itself (see my comment there).
🤖 Prompt for AI Agents |
||
| </div> | ||
|
|
||
| {purchaseDataString && ( | ||
| <div className="px-6 lg:px-8 py-7 space-y-2 border-t border-dashed"> | ||
| <p className="text-sm text-muted-foreground ">Purchase Data</p> | ||
| <p className="text-sm text-foreground ">Purchase Data</p> | ||
| <CodeClient | ||
| code={purchaseDataString} | ||
| lang="json" | ||
|
|
@@ -113,6 +120,8 @@ function TokenInfo(props: { | |
| txHash: string | undefined; | ||
| }) { | ||
| const chainQuery = useChainQuery(props.token.chainId); | ||
| const isNativeToken = | ||
| props.token.address.toLowerCase() === NATIVE_TOKEN_ADDRESS.toLowerCase(); | ||
|
|
||
| return ( | ||
| <div className="flex-1 pt-10 pb-9 px-6 lg:px-8"> | ||
|
|
@@ -121,8 +130,9 @@ function TokenInfo(props: { | |
| {props.label} | ||
| </h3> | ||
| </div> | ||
| <div className="h-6" /> | ||
|
|
||
| <div className="pb-7 pt-6 border-b border-dashed"> | ||
| <div> | ||
| <div className="flex items-center gap-3"> | ||
| <div className="relative hover:ring-2 hover:ring-offset-2 hover:ring-offset-card hover:ring-foreground/30 rounded-full"> | ||
| <Link | ||
|
|
@@ -178,52 +188,56 @@ function TokenInfo(props: { | |
| render={(data) => ( | ||
| <Link | ||
| href={`/${chainQuery.data?.slug || props.token.chainId}`} | ||
| className="text-sm text-muted-foreground leading-none hover:underline" | ||
| className="text-sm text-muted-foreground leading-none hover:underline flex items-center gap-1" | ||
| target="_blank" | ||
| > | ||
| {data} | ||
| {data}{" "} | ||
| <ArrowUpRightIcon className="size-3.5 text-muted-foreground/70 shrink-0" /> | ||
| </Link> | ||
| )} | ||
| /> | ||
| </div> | ||
| </div> | ||
| </div> | ||
|
|
||
| <div className="h-6" /> | ||
| <div className="h-8" /> | ||
|
|
||
| <div className="space-y-1.5"> | ||
| <div className="flex gap-2.5 justify-between"> | ||
| <p className="text-sm text-muted-foreground ">{props.addressLabel}</p> | ||
| <div className="space-y-4"> | ||
| <div className="space-y-1"> | ||
| <p className="text-sm text-foreground ">{props.addressLabel}</p> | ||
| <WalletAddress | ||
| address={props.walletAddress} | ||
| client={props.client} | ||
| className="py-0.5 h-auto text-sm [&>*]:!font-sans" | ||
| iconClassName="size-3.5" | ||
| className="py-0.5 h-auto text-sm [&>*]:!font-sans tabular-nums [&>*]:font-normal text-muted-foreground hover:text-foreground" | ||
| iconClassName="size-3" | ||
| shortenAddress={false} | ||
| /> | ||
|
Comment on lines
+205
to
214
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chainWalletAddress may still truncate even with shortenAddress={false}. The WalletAddress component uses max-w-full truncate internally (see wallet-address.tsx). That will still ellipsize long addresses and conflicts with MNY-268. Consider removing truncate or adding break-all/whitespace-normal in WalletAddress. I can open a follow-up PR to adjust that component if desired. Run this to confirm and spot other truncation sites: 🏁 Script executed: #!/bin/bash
rg -n --type=tsx -C2 'WalletAddress\(|className=.*truncate|break-all' apps/dashboard/src | sed -n '1,200p'Length of output: 27 I'll fix the command and verify the truncation issue. 🏁 Script executed: #!/bin/bash
# Corrected search: use --type=ts for TypeScript/TSX files, or use glob pattern
echo "=== Searching for WalletAddress usage and truncate classes ==="
rg -n --type=ts -C2 'WalletAddress\(|className=.*truncate|break-all' apps/dashboard/src 2>&1 | head -150
echo ""
echo "=== Inspecting wallet-address.tsx file ==="
fd -e tsx -e ts -path '*/wallet-address*' apps/dashboard/srcLength of output: 17973 🏁 Script executed: #!/bin/bash
# Find wallet-address component file with correct fd syntax
echo "=== Finding wallet-address component file ==="
fd -type f -name '*wallet-address*' apps/dashboard/src
echo ""
echo "=== Display wallet-address.tsx content ==="
fd -type f -name '*wallet-address*' apps/dashboard/src -exec cat {} \;
echo ""
echo "=== View bridge-status.tsx lines 200-220 ==="
sed -n '200,220p' apps/dashboard/src/app/\(app\)/\(dashboard\)/\(chain\)/\[chain_id\]/tx/\[txHash\]/bridge-status.tsx 2>/dev/null || echo "File not found, searching for it..."
echo ""
echo "=== Search for bridge-status file ==="
fd -type f -name '*bridge-status*' apps/dashboard/srcLength of output: 1383 🏁 Script executed: #!/bin/bash
# Use simpler grep to find wallet-address component
echo "=== Search for WalletAddress component definition ==="
find apps/dashboard/src -name '*.tsx' -o -name '*.ts' | xargs grep -l 'export.*WalletAddress\|function WalletAddress\|const WalletAddress' | head -20
echo ""
echo "=== Search in components directory ==="
find apps/dashboard/src -type d -name components | head -10
echo ""
echo "=== List files in components/ui ==="
ls -la apps/dashboard/src/components/ui/ 2>/dev/null | head -30
echo ""
echo "=== Search across all apps for wallet-address ==="
find . -type f -name '*wallet*' 2>/dev/null | grep -E '\.(tsx?|jsx?)$' | head -20Length of output: 3598 🏁 Script executed: #!/bin/bash
echo "=== Content of WalletAddress component ==="
cat apps/dashboard/src/@/components/blocks/wallet-address.tsx
echo ""
echo "=== Search for truncate in WalletAddress component ==="
grep -n "truncate\|max-w" apps/dashboard/src/@/components/blocks/wallet-address.tsxLength of output: 7669 WalletAddress component uses The concern is valid. The WalletAddress component (at Remove the 🤖 Prompt for AI Agents |
||
| </div> | ||
|
|
||
| <div className="flex gap-2 justify-between"> | ||
| <p className="text-sm text-muted-foreground ">Token Address</p> | ||
| <CopyTextButton | ||
| <div className="space-y-1"> | ||
| <p className="text-sm text-foreground ">Token Address</p> | ||
| <LinkWithCopyButton | ||
| href={ | ||
| isNativeToken | ||
| ? `/${chainQuery.data?.slug || props.token.chainId}` | ||
| : `/${chainQuery.data?.slug || props.token.chainId}/${props.token.address}` | ||
| } | ||
| textToShow={props.token.address} | ||
| textToCopy={props.token.address} | ||
| textToShow={`${props.token.address.slice(0, 6)}...${props.token.address.slice(-4)}`} | ||
| tooltip="Token Address" | ||
| className="text-sm translate-x-1.5" | ||
| copyIconPosition="left" | ||
| variant="ghost" | ||
| copyTooltip="Copy Token Address" | ||
| className="-translate-x-1" | ||
| /> | ||
| </div> | ||
|
|
||
| <div className="flex gap-2 justify-between"> | ||
| <p className="text-sm text-muted-foreground ">Transaction Hash</p> | ||
| <div className="space-y-1"> | ||
| <p className="text-sm text-foreground ">Transaction Hash</p> | ||
| {props.txHash ? ( | ||
| <CopyTextButton | ||
| <LinkWithCopyButton | ||
| className="-translate-x-1" | ||
| href={`/${chainQuery.data?.slug || props.token.chainId}/tx/${props.txHash}`} | ||
| textToShow={`${props.txHash.slice(0, 12)}...${props.txHash.slice(-4)}`} | ||
| textToCopy={props.txHash} | ||
| textToShow={`${props.txHash.slice(0, 6)}...${props.txHash.slice(-4)}`} | ||
| tooltip="Transaction Hash" | ||
| className="text-sm translate-x-1.5" | ||
| copyIconPosition="left" | ||
| variant="ghost" | ||
| copyTooltip="Copy Transaction Hash" | ||
| /> | ||
MananTank marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| ) : ( | ||
| <p className="text-sm text-muted-foreground ">N/A</p> | ||
|
|
@@ -288,10 +302,8 @@ function FailedBridgeStatusContent(props: { | |
| }) { | ||
| return ( | ||
| <div className="px-6 lg:px-8 py-7 space-y-1.5 border-b border-dashed"> | ||
| <h3 className="text-base font-medium tracking-tight mb-3"> | ||
| Transactions | ||
| </h3> | ||
| <div className="flex flex-col gap-2"> | ||
| <h3 className="text-lg font-medium tracking-tight mb-4">Transactions</h3> | ||
| <div className="space-y-4"> | ||
| {props.transactions.map((tx) => { | ||
| return ( | ||
| <TxHashRow | ||
|
|
@@ -328,34 +340,31 @@ function TxHashRow(props: { | |
| const chainQuery = useChainQuery(props.chainId); | ||
|
|
||
| return ( | ||
| <div className="flex items-center gap-2 justify-between"> | ||
| <div className="space-y-1"> | ||
| <div className="flex items-center gap-2"> | ||
| <Img | ||
| src={resolveSchemeWithErrorHandler({ | ||
| client: props.client, | ||
| uri: chainQuery.data?.icon?.url, | ||
| })} | ||
| alt={chainQuery.data?.name} | ||
| className="size-4 rounded-full" | ||
| className="size-3.5 rounded-full" | ||
| fallback={ | ||
| <div className="size-4 from-blue-500 to-foreground rounded-full bg-gradient-to-b" /> | ||
| <div className="size-3.5 from-blue-500 to-foreground rounded-full bg-gradient-to-b" /> | ||
| } | ||
| /> | ||
| <SkeletonContainer | ||
| skeletonData={`Chain ${props.chainId}`} | ||
| loadedData={chainQuery.data?.name} | ||
| render={(data) => ( | ||
| <p className="text-sm text-muted-foreground">{data}</p> | ||
| )} | ||
| render={(data) => <p className="text-sm text-foreground">{data}</p>} | ||
| /> | ||
| </div> | ||
| <CopyTextButton | ||
| <LinkWithCopyButton | ||
| href={`/${chainQuery.data?.slug || props.chainId}/tx/${props.txHash}`} | ||
| textToShow={props.txHash} | ||
| textToCopy={props.txHash} | ||
| textToShow={`${props.txHash.slice(0, 6)}...${props.txHash.slice(-4)}`} | ||
| tooltip="Copy Transaction Hash" | ||
| className="text-sm" | ||
| copyIconPosition="right" | ||
| variant="ghost" | ||
| copyTooltip="Copy Transaction Hash" | ||
| className="-translate-x-0.5" | ||
| /> | ||
| </div> | ||
| ); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Show full values; remove truncation (MNY-268).
Current classes enforce truncation on the button and text spans, contradicting the PR objective to show full Payment IDs/addresses/hashes. Allow wrapping instead.
Apply this diff:
Also applies to: 56-56, 62-62
🤖 Prompt for AI Agents