From 763d3de5a8db19a8022b2eda420f13a6787de100 Mon Sep 17 00:00:00 2001 From: MananTank Date: Mon, 10 Nov 2025 18:11:43 +0000 Subject: [PATCH] [MNY-303] Various UI/UX Improvements in Bridge components (#8388) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR focuses on various UI/UX improvements across multiple components in the `thirdweb` package, particularly enhancing visual consistency and user interaction within the Bridge and Token Selection components. ### Detailed summary - Adjusted font weights in several components from `600` to `500`. - Updated `Spacer` component usage for consistent spacing. - Enhanced `TokenSelection` UI with tabbed navigation for "All Tokens" and "Your Tokens". - Added fallback images for icons in `TokenAndChain` and `ChainButton`. - Refactored `CopyIcon` to use a `Button` instead of a `div` for better accessibility. - Improved loading states and skeletons in `TokenSelectionScreen`. - Simplified conditional rendering for transaction details in `PaymentReceipt`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit * **New Features** * Token selection: separate "All Tokens" and "Your Tokens" tabs with per-tab paging and "Load More" * Payment receipts: per-transaction explorer links and copy-to-clipboard controls * Enhanced success/details views showing expanded per-transaction status entries * **UI/UX Improvements** * Refined typography weights across Bridge screens for clearer hierarchy * Adjusted icon sizing and added visual fallbacks for missing chain/token icons * Improved spacing, alignment, scrolling and containment in Bridge layouts --- .changeset/wild-steaks-agree.md | 5 + .../web/ui/Bridge/TransactionPayment.tsx | 2 +- .../web/ui/Bridge/common/TokenAndChain.tsx | 2 +- .../web/ui/Bridge/common/TokenBalanceRow.tsx | 21 +- .../Bridge/common/selected-token-button.tsx | 12 +- .../payment-details/PaymentOverview.tsx | 16 +- .../payment-selection/TokenSelection.tsx | 2 +- .../Bridge/payment-success/PaymentReceipt.tsx | 207 ++++++------ .../Bridge/payment-success/SuccessScreen.tsx | 10 +- .../ui/Bridge/swap-widget/select-chain.tsx | 21 +- .../ui/Bridge/swap-widget/select-token-ui.tsx | 304 +++++++++++------- .../screens/Buy/swap/WalletRow.tsx | 8 +- .../src/react/web/ui/components/CopyIcon.tsx | 17 +- .../src/react/web/ui/components/Spacer.tsx | 1 + 14 files changed, 353 insertions(+), 275 deletions(-) create mode 100644 .changeset/wild-steaks-agree.md diff --git a/.changeset/wild-steaks-agree.md b/.changeset/wild-steaks-agree.md new file mode 100644 index 00000000000..fce8bc7568c --- /dev/null +++ b/.changeset/wild-steaks-agree.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +- Various UI/UX Improvements in Bridge components diff --git a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx index f58b08a6671..9cca1234a8f 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/TransactionPayment.tsx @@ -219,7 +219,7 @@ export function TransactionPayment({ }} > {/* USD Value */} - + {costToDisplay} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/common/TokenAndChain.tsx b/packages/thirdweb/src/react/web/ui/Bridge/common/TokenAndChain.tsx index c36dad4e7ec..3ab0a3a5855 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/common/TokenAndChain.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/common/TokenAndChain.tsx @@ -82,7 +82,7 @@ export function TokenAndChain({ textOverflow: "ellipsis", whiteSpace: "nowrap", }} - weight={600} + weight={500} trackingTight > {token.name} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/common/TokenBalanceRow.tsx b/packages/thirdweb/src/react/web/ui/Bridge/common/TokenBalanceRow.tsx index 84a77e39a61..9121abcff8f 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/common/TokenBalanceRow.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/common/TokenBalanceRow.tsx @@ -68,18 +68,9 @@ export function TokenBalanceRow({ overflow: "hidden", }} > - - + + diff --git a/packages/thirdweb/src/react/web/ui/Bridge/common/selected-token-button.tsx b/packages/thirdweb/src/react/web/ui/Bridge/common/selected-token-button.tsx index ac732a8a9e4..ed166445c14 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/common/selected-token-button.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/common/selected-token-button.tsx @@ -100,13 +100,23 @@ export function SelectedTokenButton(props: { }} > + } /> )} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentOverview.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentOverview.tsx index e3345bc7bd6..e3ba81ad9df 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentOverview.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-details/PaymentOverview.tsx @@ -63,7 +63,7 @@ export function PaymentOverview(props: { @@ -91,13 +91,14 @@ export function PaymentOverview(props: { py="sm" style={{ justifyContent: "space-between" }} > + {/* left */} {getFiatCurrencyIcon({ currency: props.paymentMethod.currency, size: "lg", })} - + {props.paymentMethod.currency} @@ -106,7 +107,8 @@ export function PaymentOverview(props: { - + {/* right */} + {props.fromAmount} @@ -136,11 +138,12 @@ export function PaymentOverview(props: { )} + {props.modeInfo.mode === "direct_payment" && ( - + {props.metadata.title || "Payment"} {props.metadata.description && ( @@ -173,7 +176,6 @@ export function PaymentOverview(props: { size="sm" token={props.toToken} tokenAmount={props.modeInfo.paymentInfo.amount} - weight={600} /> {props.modeInfo.paymentInfo.amount} {props.toToken.symbol} @@ -285,7 +287,7 @@ const TransactionOverViewCompact = (props: { style={{ justifyContent: "space-between" }} > - + {props.metadata.title || "Transaction"} {props.metadata.description && ( diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/TokenSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/TokenSelection.tsx index de2dfa41bb0..e50ef3f9165 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/TokenSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/TokenSelection.tsx @@ -89,7 +89,7 @@ function PaymentMethodTokenRow({ {formatCurrencyAmount( currency || "USD", diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-success/PaymentReceipt.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-success/PaymentReceipt.tsx index 585af650933..ec711b9ae27 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-success/PaymentReceipt.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-success/PaymentReceipt.tsx @@ -1,7 +1,5 @@ "use client"; -import { CopyIcon } from "@radix-ui/react-icons"; import { useQuery } from "@tanstack/react-query"; -import { useCallback } from "react"; import type { Token } from "../../../../../bridge/types/Token.js"; import type { ChainMetadata } from "../../../../../chains/types.js"; import { @@ -10,22 +8,18 @@ import { getChainMetadata, } from "../../../../../chains/utils.js"; import { shortenHex } from "../../../../../utils/address.js"; -import { formatExplorerTxUrl } from "../../../../../utils/url.js"; import type { WindowAdapter } from "../../../../core/adapters/WindowAdapter.js"; import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; -import { - iconSize, - radius, - spacing, -} from "../../../../core/design-system/index.js"; +import { radius, spacing } from "../../../../core/design-system/index.js"; import type { BridgePrepareResult } from "../../../../core/hooks/useBridgePrepare.js"; import type { CompletedStatusResult } from "../../../../core/hooks/useStepExecutor.js"; import { formatTokenAmount } from "../../ConnectWallet/screens/formatTokenBalance.js"; -import { Container, ModalHeader } from "../../components/basic.js"; +import { Container, Line, ModalHeader } from "../../components/basic.js"; import { shorterChainName } from "../../components/ChainName.js"; +import { CopyIcon } from "../../components/CopyIcon.js"; import { Skeleton } from "../../components/Skeleton.js"; import { Spacer } from "../../components/Spacer.js"; -import { Text } from "../../components/text.js"; +import { Link, Text } from "../../components/text.js"; interface TransactionInfo { type: "paymentId" | "transactionHash"; @@ -128,7 +122,6 @@ interface CompletedStepDetailCardProps { status: CompletedStatusResult; preparedQuote: BridgePrepareResult; windowAdapter: WindowAdapter; - onCopyToClipboard: (text: string) => Promise; } /** @@ -137,29 +130,12 @@ interface CompletedStepDetailCardProps { function CompletedStepDetailCard({ status, preparedQuote, - windowAdapter, - onCopyToClipboard, }: CompletedStepDetailCardProps) { const theme = useCustomTheme(); - const { data: txInfo, isLoading } = useTransactionInfo(status, preparedQuote); + const { data: txInfo, isPending } = useTransactionInfo(status, preparedQuote); - if (isLoading) { - return ( - - - - - - ); + if (isPending) { + return ; } if (!txInfo) { @@ -174,7 +150,7 @@ function CompletedStepDetailCard({ style={{ backgroundColor: theme.colors.tertiaryBg, border: `1px solid ${theme.colors.borderColor}`, - borderRadius: radius.sm, + borderRadius: radius.lg, padding: spacing.md, }} > @@ -182,27 +158,37 @@ function CompletedStepDetailCard({ - + {txInfo.label} - + COMPLETED + + {/* Amount Paid */} {txInfo.amountPaid && ( )} - {/* Origin Chain */} - {txInfo.originChain && ( + {/* Amount Received */} + {txInfo.amountReceived && ( - Origin Chain + Amount Received - {shorterChainName(txInfo.originChain.name)} + {txInfo.amountReceived} )} - {/* Amount Received */} - {txInfo.amountReceived && ( + {/* Origin Chain */} + {txInfo.originChain && ( - Amount Received + Origin Chain - {txInfo.amountReceived} + {shorterChainName(txInfo.originChain.name)} )} - {/* Chain */} + {/* Destination Chain */} - Chain + Destination Chain {shorterChainName(txInfo.chain.name)} @@ -266,58 +252,59 @@ function CompletedStepDetailCard({ {/* Transaction Info */} - - - {txInfo.type === "paymentId" ? "Payment ID" : "Transaction Hash"} - - - onCopyToClipboard(txInfo.id) - : () => { - const explorer = txInfo.chain.explorers?.[0]; - if (explorer) { - windowAdapter.open( - formatExplorerTxUrl(explorer.url, txInfo.id), - ); - } - } - } - size="sm" - style={{ - cursor: "pointer", - fontFamily: "monospace", - }} - > - {shortenHex(txInfo.id)} + {txInfo.type === "paymentId" && ( + + + Payment ID + + - {txInfo.type === "paymentId" ? ( - - ) : null} - - + + + {shortenHex(tx.transactionHash)} + + + + ); + })} ); } @@ -350,34 +337,23 @@ export function PaymentReceipt({ onBack, windowAdapter, }: PaymentReceitProps) { - // Copy to clipboard - const copyToClipboard = useCallback(async (text: string) => { - try { - await navigator.clipboard.writeText(text); - // Could add a toast notification here - } catch (error) { - console.warn("Failed to copy to clipboard:", error); - } - }, []); - return ( - + + + - - - + {/* Status Results */} - + {completedStatuses.map((status, index) => ( + ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx index bcafd515e93..76d797138c4 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-success/SuccessScreen.tsx @@ -9,7 +9,7 @@ import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvid import { iconSize, spacing } from "../../../../core/design-system/index.js"; import type { BridgePrepareResult } from "../../../../core/hooks/useBridgePrepare.js"; import type { CompletedStatusResult } from "../../../../core/hooks/useStepExecutor.js"; -import { Container, ModalHeader } from "../../components/basic.js"; +import { Container } from "../../components/basic.js"; import { Button } from "../../components/buttons.js"; import { Spacer } from "../../components/Spacer.js"; import { Text } from "../../components/text.js"; @@ -91,9 +91,7 @@ export function SuccessScreen({ return ( - - - + {/* Success Icon with Animation */} @@ -130,7 +128,7 @@ export function SuccessScreen({ marginBottom: spacing.xxs, }} > - Payment Successful! + Payment Successful @@ -143,7 +141,7 @@ export function SuccessScreen({ - + {/* Action Buttons */} diff --git a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsx b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsx index eb19b1ee2da..9f894de85f7 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-chain.tsx @@ -1,6 +1,7 @@ import { useMemo, useState } from "react"; import type { Chain as BridgeChain } from "../../../../../bridge/index.js"; import type { ThirdwebClient } from "../../../../../client/client.js"; +import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; import { fontSize, iconSize, @@ -170,6 +171,8 @@ function ChainButton(props: { isSelected: boolean; isMobile: boolean; }) { + const theme = useCustomTheme(); + const iconSizeValue = props.isMobile ? iconSize.lg : iconSize.md; return ( diff --git a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-token-ui.tsx b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-token-ui.tsx index b587ae214a3..dd103765cbf 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-token-ui.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/swap-widget/select-token-ui.tsx @@ -1,4 +1,4 @@ -import { useMemo, useState } from "react"; +import { useCallback, useMemo, useState } from "react"; import type { Token } from "../../../../../bridge/index.js"; import type { BridgeChain } from "../../../../../bridge/types/Chain.js"; import type { ThirdwebClient } from "../../../../../client/client.js"; @@ -10,8 +10,6 @@ import { radius, spacing, } from "../../../../core/design-system/index.js"; -import { CoinsIcon } from "../../ConnectWallet/icons/CoinsIcon.js"; -import { WalletDotIcon } from "../../ConnectWallet/icons/WalletDotIcon.js"; import { Container, noScrollBar } from "../../components/basic.js"; import { Button } from "../../components/buttons.js"; import { Img } from "../../components/Img.js"; @@ -52,14 +50,18 @@ function findChain(chains: BridgeChain[], activeChainId: number | undefined) { return chains.find((chain) => chain.chainId === activeChainId); } +const ALL_TOKENS_LIMIT = 100; +const OWNED_TOKENS_LIMIT = 50; + /** * @internal */ export function SelectToken(props: SelectTokenUIProps) { const chainQuery = useBridgeChains(props.client); - const [search, setSearch] = useState(""); + const [search, _setSearch] = useState(""); const debouncedSearch = useDebouncedValue(search, 500); - const [limit, setLimit] = useState(1000); + const [allTokensLimit, setAllTokensLimit] = useState(ALL_TOKENS_LIMIT); + const [ownedTokensLimit, setOwnedTokensLimit] = useState(OWNED_TOKENS_LIMIT); const [_selectedChain, setSelectedChain] = useState( undefined, @@ -77,7 +79,7 @@ export function SelectToken(props: SelectTokenUIProps) { client: props.client, chainId: selectedChain?.chainId, search: debouncedSearch, - limit, + limit: allTokensLimit, offset: 0, }); @@ -85,7 +87,7 @@ export function SelectToken(props: SelectTokenUIProps) { const ownedTokensQuery = useTokenBalances({ clientId: props.client.clientId, chainId: selectedChain?.chainId, - limit, + limit: ownedTokensLimit, page: 1, walletAddress: props.activeWalletInfo?.activeAccount.address, }); @@ -102,43 +104,62 @@ export function SelectToken(props: SelectTokenUIProps) { }); }, [ownedTokensQuery.data?.tokens, debouncedSearch]); - const isFetching = tokensQuery.isFetching || ownedTokensQuery.isFetching; + const setSearch = useCallback((search: string) => { + _setSearch(search); + setAllTokensLimit(ALL_TOKENS_LIMIT); + setOwnedTokensLimit(OWNED_TOKENS_LIMIT); + }, []); return ( { + setOwnedTokensLimit(ownedTokensLimit + OWNED_TOKENS_LIMIT); + } + : undefined, + }} + allTokens={{ + data: tokensQuery.data || [], + isFetching: tokensQuery.isFetching, + showMore: + tokensQuery.data?.length === allTokensLimit + ? () => { + setAllTokensLimit(allTokensLimit + ALL_TOKENS_LIMIT); + } + : undefined, + }} selectedChain={selectedChain} setSelectedChain={setSelectedChain} search={search} setSearch={setSearch} selectedToken={props.selectedToken} setSelectedToken={props.setSelectedToken} - showMore={ - tokensQuery.data?.length === limit - ? () => { - setLimit(limit * 2); - } - : undefined - } /> ); } function SelectTokenUI( props: SelectTokenUIProps & { - ownedTokens: TokenBalance[]; - allTokens: Token[]; - isFetching: boolean; + allTokens: { + data: Token[]; + isFetching: boolean; + showMore: (() => void) | undefined; + }; + ownedTokens: { + data: TokenBalance[]; + isFetching: boolean; + showMore: (() => void) | undefined; + }; selectedChain: BridgeChain | undefined; setSelectedChain: (chain: BridgeChain) => void; search: string; setSearch: (search: string) => void; selectedToken: TokenSelection | undefined; setSelectedToken: (token: TokenSelection) => void; - showMore: (() => void) | undefined; }, ) { const isMobile = useIsMobile(); @@ -148,7 +169,7 @@ function SelectTokenUI( // show tokens with icons first const sortedOwnedTokens = useMemo(() => { - return props.ownedTokens.sort((a, b) => { + return props.ownedTokens.data.sort((a, b) => { if (a.icon_uri && !b.icon_uri) { return -1; } @@ -157,23 +178,11 @@ function SelectTokenUI( } return 0; }); - }, [props.ownedTokens]); - - const otherTokens = useMemo(() => { - const ownedTokenSet = new Set( - sortedOwnedTokens.map((t) => - `${t.token_address}-${t.chain_id}`.toLowerCase(), - ), - ); - return props.allTokens.filter( - (token) => - !ownedTokenSet.has(`${token.address}-${token.chainId}`.toLowerCase()), - ); - }, [props.allTokens, sortedOwnedTokens]); + }, [props.ownedTokens.data]); // show tokens with icons first - const sortedOtherTokens = useMemo(() => { - return otherTokens.sort((a, b) => { + const sortedAllTokens = useMemo(() => { + return props.allTokens.data.sort((a, b) => { if (a.iconUri && !b.iconUri) { return -1; } @@ -182,7 +191,7 @@ function SelectTokenUI( } return 0; }); - }, [otherTokens]); + }, [props.allTokens.data]); // desktop if (!isMobile) { @@ -214,15 +223,20 @@ function SelectTokenUI( }} isMobile={false} selectedToken={props.selectedToken} - isFetching={props.isFetching} - ownedTokens={props.ownedTokens} - otherTokens={sortedOtherTokens} - showMore={props.showMore} + ownedTokens={{ + ...props.ownedTokens, + data: sortedOwnedTokens, + }} + allTokens={{ + ...props.allTokens, + data: sortedAllTokens, + }} selectedChain={props.selectedChain} onSelectChain={() => setScreen("select-chain")} client={props.client} search={props.search} setSearch={props.setSearch} + isWalletConnected={props.activeWalletInfo !== undefined} /> @@ -232,15 +246,20 @@ function SelectTokenUI( if (screen === "select-token") { return ( { props.setSelectedToken(token); props.onClose(); }} selectedToken={props.selectedToken} - isFetching={props.isFetching} - ownedTokens={props.ownedTokens} - otherTokens={sortedOtherTokens} - showMore={props.showMore} + ownedTokens={{ + ...props.ownedTokens, + data: sortedOwnedTokens, + }} + allTokens={{ + ...props.allTokens, + data: sortedAllTokens, + }} selectedChain={props.selectedChain} isMobile={true} onSelectChain={() => setScreen("select-chain")} @@ -428,17 +447,36 @@ function TokenSelectionScreen(props: { client: ThirdwebClient; search: string; setSearch: (search: string) => void; - isFetching: boolean; - ownedTokens: TokenBalance[]; - otherTokens: Token[]; - showMore: (() => void) | undefined; selectedToken: TokenSelection | undefined; onSelectToken: (token: TokenSelection) => void; + isWalletConnected: boolean; + allTokens: { + data: Token[]; + isFetching: boolean; + showMore: (() => void) | undefined; + }; + ownedTokens: { + data: TokenBalance[]; + isFetching: boolean; + showMore: (() => void) | undefined; + }; }) { - const noTokensFound = - !props.isFetching && - props.otherTokens.length === 0 && - props.ownedTokens.length === 0; + const noAllTokensFound = + !props.allTokens.isFetching && props.allTokens.data.length === 0; + + const noOwnedTokensFound = + !props.ownedTokens.isFetching && props.ownedTokens.data.length === 0; + + const [activeTab, setActiveTab] = useState<"owned" | "all">("all"); + const showSkeletons = + (props.allTokens.isFetching && activeTab === "all") || + (props.ownedTokens.isFetching && activeTab === "owned"); + + const showNoTokensFound = + (activeTab === "all" && noAllTokensFound) || + (activeTab === "owned" && noOwnedTokensFound); + + const theme = useCustomTheme(); return ( @@ -448,16 +486,14 @@ function TokenSelectionScreen(props: { - Select a token from the list or search for a token by symbol or - address + Select a token from the list or use the search @@ -467,7 +503,7 @@ function TokenSelectionScreen(props: { display: "flex", alignItems: "center", justifyContent: "center", - minHeight: "400px", + minHeight: "300px", }} > @@ -498,7 +534,28 @@ function TokenSelectionScreen(props: { /> - + + + {/* tabs */} + {props.isWalletConnected && ( + + setActiveTab("all")} + label="All Tokens" + /> + setActiveTab("owned")} + label="Your Tokens" + /> + + )} - {props.isFetching && + {props.isWalletConnected && } + + {showSkeletons && new Array(20).fill(0).map((_, i) => ( // biome-ignore lint/suspicious/noArrayIndexKey: ok ))} - {!props.isFetching && props.ownedTokens.length > 0 && ( - - - - Your Tokens - - - )} - - {!props.isFetching && - props.ownedTokens.map((token) => ( + {activeTab === "owned" && + !props.ownedTokens.isFetching && + props.ownedTokens.data.map((token) => ( ))} - {!props.isFetching && props.ownedTokens.length > 0 && ( - - - - Other Tokens - - - )} - - {!props.isFetching && - props.otherTokens.map((token) => ( + {activeTab === "all" && + !props.allTokens.isFetching && + props.allTokens.data.map((token) => ( ))} - {props.showMore && ( + {activeTab === "all" && props.allTokens.showMore && ( )} - {noTokensFound && ( + {activeTab === "owned" && props.ownedTokens.showMore && ( + + )} + + {showNoTokensFound && (
- + No Tokens Found
@@ -643,3 +669,45 @@ const LeftContainer = /* @__PURE__ */ StyledDiv((_) => { position: "relative", }; }); + +function TabButton(props: { + isSelected: boolean; + onSelect: () => void; + label: string; +}) { + const theme = useCustomTheme(); + return ( +
+ + + {props.isSelected && ( +
+ )} +
+ ); +} diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/WalletRow.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/WalletRow.tsx index f29463d4f3e..5d46b2e6818 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/WalletRow.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/Buy/swap/WalletRow.tsx @@ -46,17 +46,19 @@ export function WalletRow(props: { const addressOrENS = address ? ensNameQuery.data || shortenAddress(address) : ""; + + const iconSizeValue = iconSize[props.iconSize || "md"]; return ( - + {wallet ? ( ) : ( - + )} {props.label ? ( diff --git a/packages/thirdweb/src/react/web/ui/components/CopyIcon.tsx b/packages/thirdweb/src/react/web/ui/components/CopyIcon.tsx index baf6b8eb6d4..f84cc28d0f6 100644 --- a/packages/thirdweb/src/react/web/ui/components/CopyIcon.tsx +++ b/packages/thirdweb/src/react/web/ui/components/CopyIcon.tsx @@ -1,7 +1,9 @@ "use client"; import { CheckIcon, CopyIcon as CopyIconSVG } from "@radix-ui/react-icons"; +import { radius } from "../../../core/design-system/index.js"; import { useClipboard } from "../hooks/useCopyClipboard.js"; import { Container } from "./basic.js"; +import { Button } from "./buttons.js"; import { ToolTip } from "./Tooltip.js"; /** @@ -19,25 +21,22 @@ export const CopyIcon: React.FC<{ const showCheckIcon = props.hasCopied || hasCopied; return ( - // biome-ignore lint/a11y/noStaticElementInteractions: TODO -
{ - if (e.key === "Enter" || e.key === " ") { - onCopy(); - } - }} + variant="ghost-solid" style={{ alignItems: "center", display: "flex", + padding: 2, justifyContent: "center", + borderRadius: radius.sm, }} >
{showCheckIcon ? ( @@ -56,6 +55,6 @@ export const CopyIcon: React.FC<{
-
+ ); }; diff --git a/packages/thirdweb/src/react/web/ui/components/Spacer.tsx b/packages/thirdweb/src/react/web/ui/components/Spacer.tsx index d40f5ed418d..2cd460a906d 100644 --- a/packages/thirdweb/src/react/web/ui/components/Spacer.tsx +++ b/packages/thirdweb/src/react/web/ui/components/Spacer.tsx @@ -8,6 +8,7 @@ export const Spacer: React.FC<{ y: keyof typeof spacing }> = ({ y }) => {
);