diff --git a/.changeset/mean-mails-exercise.md b/.changeset/mean-mails-exercise.md new file mode 100644 index 00000000000..db4ceb0415f --- /dev/null +++ b/.changeset/mean-mails-exercise.md @@ -0,0 +1,20 @@ +--- +"thirdweb": minor +--- + +Allow to customize the display order of Asset tabs + +When you click on "View Assets", by default the "Tokens" tab is shown first. + +If you want to show the "NFTs" tab first, change the order of the asset tabs to: ["nft", "token"] + +Note: If an empty array is passed, the [View Funds] button will be hidden + +```tsx + +``` \ No newline at end of file diff --git a/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts b/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts index 2cab2aeac06..9c4bad41dde 100644 --- a/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts +++ b/packages/thirdweb/src/react/core/hooks/connection/ConnectButtonProps.ts @@ -3,6 +3,7 @@ import type { ThirdwebClient } from "../../../../client/client.js"; import type { BuyWithCryptoStatus } from "../../../../pay/buyWithCrypto/getStatus.js"; import type { BuyWithFiatStatus } from "../../../../pay/buyWithFiat/getStatus.js"; import type { FiatProvider } from "../../../../pay/utils/commonTypes.js"; +import type { AssetTabs } from "../../../../react/web/ui/ConnectWallet/screens/ViewAssets.js"; import type { PreparedTransaction } from "../../../../transaction/prepare-transaction.js"; import type { Prettify } from "../../../../utils/type-utils.js"; import type { Account, Wallet } from "../../../../wallets/interfaces/wallet.js"; @@ -311,6 +312,13 @@ export type ConnectButton_detailsModalOptions = { * All wallet IDs included in this array will be hidden from wallet selection when connected. */ hiddenWallets?: WalletId[]; + + /** + * When you click on "View Assets", by default the "Tokens" tab is shown first. + * If you want to show the "NFTs" tab first, change the order of the asset tabs to: ["nft", "token"] + * Note: If an empty array is passed, the [View Funds] button will be hidden + */ + assetTabs?: AssetTabs[]; }; /** diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx index ab7c3e27a24..2cb0cfdf25b 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/ConnectButton.tsx @@ -247,6 +247,20 @@ const TW_CONNECT_WALLET = "tw-connect-wallet"; * /> * ``` * + * ### Customizing the orders of the tabs in the [View Funds] screen + * When you click on "View Assets", by default the "Tokens" tab is shown first. + * If you want to show the "NFTs" tab first, change the order of the asset tabs to: ["nft", "token"] + * Note: If an empty array is passed, the [View Funds] button will be hidden + * + * ```tsx + * + * ``` + * * @param props * Props for the `ConnectButton` component * diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx index 8aebe86dd70..07493237f58 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/Details.tsx @@ -109,7 +109,7 @@ import { ManageWalletScreen } from "./screens/ManageWalletScreen.js"; import { PrivateKey } from "./screens/PrivateKey.js"; import { ReceiveFunds } from "./screens/ReceiveFunds.js"; import { SendFunds } from "./screens/SendFunds.js"; -import { ViewAssets } from "./screens/ViewAssets.js"; +import { type AssetTabs, ViewAssets } from "./screens/ViewAssets.js"; import { ViewNFTs } from "./screens/ViewNFTs.js"; import { ViewTokens } from "./screens/ViewTokens.js"; import { WalletConnectReceiverScreen } from "./screens/WalletConnectReceiverScreen.js"; @@ -170,6 +170,7 @@ export const ConnectedWalletDetails: React.FC<{ chains={props.chains} displayBalanceToken={props.detailsButton?.displayBalanceToken} connectOptions={props.connectOptions} + assetTabs={props.detailsModal?.assetTabs} />, ); } @@ -284,6 +285,7 @@ function DetailsModal(props: { chains: Chain[]; displayBalanceToken?: Record; connectOptions: DetailsModalConnectOptions | undefined; + assetTabs?: AssetTabs[]; }) { const [screen, setScreen] = useState("main"); const { disconnect } = useDisconnect(); @@ -627,21 +629,24 @@ function DetailsModal(props: { {/* View Funds */} - { - setScreen("view-assets"); - }} - style={{ - fontSize: fontSize.sm, - }} - > - - - {props.supportedNFTs - ? locale.viewFunds.viewAssets - : locale.viewFunds.title} - - + {/* Hide the View Funds button if the assetTabs props is set to an empty array */} + {(props.assetTabs === undefined || props.assetTabs.length) && ( + { + setScreen("view-assets"); + }} + style={{ + fontSize: fontSize.sm, + }} + > + + + {props.supportedNFTs + ? locale.viewFunds.viewAssets + : locale.viewFunds.title} + + + )} {/* Manage Wallet */} ); } else { @@ -1458,6 +1464,13 @@ export type UseWalletDetailsModalOptions = { * By default the "Buy Funds" button is shown. */ hideBuyFunds?: boolean; + + /** + * When you click on "View Assets", by default the "Tokens" tab is shown first. + * If you want to show the "NFTs" tab first, change the order of the asset tabs to: ["nft", "token"] + * Note: If an empty array is passed, the [View Funds] button will be hidden + */ + assetTabs?: AssetTabs[]; }; /** @@ -1515,6 +1528,7 @@ export function useWalletDetailsModal() { hideBuyFunds: props.hideBuyFunds, hideReceiveFunds: props.hideReceiveFunds, hideSendFunds: props.hideSendFunds, + assetTabs: props.assetTabs, }} displayBalanceToken={props.displayBalanceToken} theme={props.theme || "dark"} diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx index fc62951418e..b42cb939ff4 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useMemo, useState } from "react"; import type { ThirdwebClient } from "../../../../../client/client.js"; import { type Theme, iconSize } from "../../../../core/design-system/index.js"; import type { @@ -15,6 +15,29 @@ import { ViewNFTsContent } from "./ViewNFTs.js"; import { ViewTokensContent } from "./ViewTokens.js"; import type { WalletDetailsModalScreen } from "./types.js"; +/** + * @internal + */ +export type AssetTabs = "token" | "nft"; + +const TokenTab = { + label: ( + + Tokens + + ), + value: "Tokens", +}; + +const NftTab = { + label: ( + + NFTs + + ), + value: "NFTs", +}; + /** * @internal */ @@ -26,9 +49,29 @@ export function ViewAssets(props: { setScreen: (screen: WalletDetailsModalScreen) => void; client: ThirdwebClient; connectLocale: ConnectLocale; + assetTabs?: AssetTabs[]; }) { - const [activeTab, setActiveTab] = useState("Tokens"); const { connectLocale } = props; + const options = useMemo(() => { + if (!props.assetTabs) { + return [TokenTab, NftTab]; + } + if (!props.assetTabs.length) { + return []; + } + const tabs = []; + for (const item of props.assetTabs) { + if (item === "token") { + tabs.push(TokenTab); + } else if (item === "nft") { + tabs.push(NftTab); + } + } + return tabs; + }, [props.assetTabs]); + + // Since `options` is now a dynamic value, the default active tab is set to the value of the first tab in `options` + const [activeTab, setActiveTab] = useState(options[0]?.value || "Tokens"); return ( - - Tokens - - ), - value: "Tokens", - }, - { - label: ( - - NFTs - - ), - value: "NFTs", - }, - ]} - selected={activeTab} - onSelect={setActiveTab} - > +