Skip to content

Commit

Permalink
add asChild prop to UI components
Browse files Browse the repository at this point in the history
  • Loading branch information
jnsdls committed Jan 30, 2025
1 parent 1ee0dff commit 7bda6cd
Show file tree
Hide file tree
Showing 21 changed files with 121 additions and 85 deletions.
5 changes: 5 additions & 0 deletions .changeset/funny-taxis-grow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

allow passing `asChild` for most ui components
2 changes: 1 addition & 1 deletion apps/dashboard/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@radix-ui/react-radio-group": "^1.2.2",
"@radix-ui/react-select": "^2.1.5",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tooltip": "1.1.7",
"@sentry/nextjs": "8.52.0",
Expand Down
2 changes: 1 addition & 1 deletion apps/playground-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@radix-ui/react-scroll-area": "^1.2.2",
"@radix-ui/react-select": "^2.1.5",
"@radix-ui/react-separator": "^1.1.1",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-switch": "^1.1.2",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-tooltip": "1.1.7",
Expand Down
2 changes: 1 addition & 1 deletion apps/portal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"@radix-ui/react-dialog": "1.1.5",
"@radix-ui/react-dropdown-menu": "^2.1.5",
"@radix-ui/react-select": "^2.1.5",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@tanstack/react-query": "5.65.1",
"@tryghost/content-api": "^1.11.21",
Expand Down
2 changes: 1 addition & 1 deletion apps/wallet-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@radix-ui/react-dialog": "1.1.5",
"@radix-ui/react-label": "^2.1.1",
"@radix-ui/react-popover": "^1.1.5",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-slot": "1.1.1",
"@tanstack/react-query": "5.65.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
Expand Down
77 changes: 20 additions & 57 deletions packages/thirdweb/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -132,63 +132,25 @@
},
"typesVersions": {
"*": {
"adapters/*": [
"./dist/types/exports/adapters/*.d.ts"
],
"auth": [
"./dist/types/exports/auth.d.ts"
],
"chains": [
"./dist/types/exports/chains.d.ts"
],
"contract": [
"./dist/types/exports/contract.d.ts"
],
"deploys": [
"./dist/types/exports/deploys.d.ts"
],
"event": [
"./dist/types/exports/event.d.ts"
],
"extensions/*": [
"./dist/types/exports/extensions/*.d.ts"
],
"pay": [
"./dist/types/exports/pay.d.ts"
],
"react": [
"./dist/types/exports/react.d.ts"
],
"react-native": [
"./dist/types/exports/react-native.d.ts"
],
"rpc": [
"./dist/types/exports/rpc.d.ts"
],
"storage": [
"./dist/types/exports/storage.d.ts"
],
"transaction": [
"./dist/types/exports/transaction.d.ts"
],
"utils": [
"./dist/types/exports/utils.d.ts"
],
"wallets": [
"./dist/types/exports/wallets.d.ts"
],
"wallets/*": [
"./dist/types/exports/wallets/*.d.ts"
],
"modules": [
"./dist/types/exports/modules.d.ts"
],
"social": [
"./dist/types/exports/social.d.ts"
],
"ai": [
"./dist/types/exports/ai.d.ts"
]
"adapters/*": ["./dist/types/exports/adapters/*.d.ts"],
"auth": ["./dist/types/exports/auth.d.ts"],
"chains": ["./dist/types/exports/chains.d.ts"],
"contract": ["./dist/types/exports/contract.d.ts"],
"deploys": ["./dist/types/exports/deploys.d.ts"],
"event": ["./dist/types/exports/event.d.ts"],
"extensions/*": ["./dist/types/exports/extensions/*.d.ts"],
"pay": ["./dist/types/exports/pay.d.ts"],
"react": ["./dist/types/exports/react.d.ts"],
"react-native": ["./dist/types/exports/react-native.d.ts"],
"rpc": ["./dist/types/exports/rpc.d.ts"],
"storage": ["./dist/types/exports/storage.d.ts"],
"transaction": ["./dist/types/exports/transaction.d.ts"],
"utils": ["./dist/types/exports/utils.d.ts"],
"wallets": ["./dist/types/exports/wallets.d.ts"],
"wallets/*": ["./dist/types/exports/wallets/*.d.ts"],
"modules": ["./dist/types/exports/modules.d.ts"],
"social": ["./dist/types/exports/social.d.ts"],
"ai": ["./dist/types/exports/ai.d.ts"]
}
},
"browser": {
Expand Down Expand Up @@ -217,6 +179,7 @@
"@radix-ui/react-dialog": "1.1.5",
"@radix-ui/react-focus-scope": "1.1.1",
"@radix-ui/react-icons": "1.3.2",
"@radix-ui/react-slot": "1.1.1",
"@radix-ui/react-tooltip": "1.1.7",
"@tanstack/react-query": "5.65.1",
"@walletconnect/ethereum-provider": "2.17.5",
Expand Down
8 changes: 6 additions & 2 deletions packages/thirdweb/src/react/web/ui/SiteLink.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"use client";
import * as Slot from "@radix-ui/react-slot";
import { useQuery } from "@tanstack/react-query";
import type { ThirdwebClient } from "../../../client/client.js";
import { getLastAuthProvider } from "../../../react/core/utils/storage.js";
Expand Down Expand Up @@ -34,8 +35,10 @@ export function SiteLink({
client,
ecosystem,
children,
asChild,
...props
}: {
asChild?: boolean;
href: string;
client: ThirdwebClient;
ecosystem?: Ecosystem;
Expand Down Expand Up @@ -82,9 +85,10 @@ export function SiteLink({
url.searchParams.set("authCookie", authCookie);
}

const Comp = asChild ? Slot.Root : "a";
return (
<a href={encodeURI(url.toString())} {...props}>
<Comp href={encodeURI(url.toString())} {...props}>
{children}
</a>
</Comp>
);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { useAccountContext } from "../../../../core/account/provider.js";

/**
Expand All @@ -8,6 +9,7 @@ import { useAccountContext } from "../../../../core/account/provider.js";
*/
export interface AccountAddressProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
asChild?: boolean;
/**
* The function used to transform (format) the wallet address
* Specifically useful for shortening the wallet.
Expand Down Expand Up @@ -56,9 +58,11 @@ export interface AccountAddressProps
*/
export function AccountAddress({
formatFn,
asChild,
...restProps
}: AccountAddressProps) {
const { address } = useAccountContext();
const value = formatFn ? formatFn(address) : address;
return <span {...restProps}>{value}</span>;
const Comp = asChild ? Slot.Root : "span";
return <Comp {...restProps}>{value}</Comp>;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type React from "react";
import type { JSX } from "react";
Expand All @@ -20,6 +21,7 @@ import { useAccountContext } from "../../../../core/account/provider.js";
export interface AccountAvatarProps
extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src">,
Omit<ResolveNameOptions, "client" | "address"> {
asChild?: boolean;
/**
* Use this prop to prioritize the social profile that you want to display
* This is useful for a wallet containing multiple social profiles.
Expand Down Expand Up @@ -159,6 +161,7 @@ export function AccountAvatar({
loadingComponent,
fallbackComponent,
queryOptions,
asChild,
...restProps
}: AccountAvatarProps) {
const { address, client } = useAccountContext();
Expand Down Expand Up @@ -222,5 +225,6 @@ export function AccountAvatar({
return fallbackComponent || null;
}

return <img src={avatarQuery.data} {...restProps} alt={restProps.alt} />;
const Comp = asChild ? Slot.Root : "img";
return <Comp src={avatarQuery.data} {...restProps} alt={restProps.alt} />;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type React from "react";
import type { JSX } from "react";
Expand All @@ -22,6 +23,7 @@ import { formatAccountTokenBalance } from "../../../../core/utils/account.js";
*/
export interface AccountBalanceProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
asChild?: boolean;
/**
* The network to fetch balance on
* If not passed, the component will use the current chain that the wallet is connected to (`useActiveWalletChain()`)
Expand Down Expand Up @@ -166,6 +168,7 @@ export function AccountBalance({
queryOptions,
formatFn,
showBalanceInFiat,
asChild,
...restProps
}: AccountBalanceProps) {
const { address, client } = useAccountContext();
Expand Down Expand Up @@ -212,12 +215,13 @@ export function AccountBalance({
);
}

const Comp = asChild ? Slot.Root : "span";
return (
<span {...restProps}>
<Comp {...restProps}>
{formatAccountTokenBalance({
...balanceQuery.data,
decimals: balanceQuery.data.balance < 1 ? 3 : 2,
})}
</span>
</Comp>
);
}
6 changes: 5 additions & 1 deletion packages/thirdweb/src/react/web/ui/prebuilt/Account/name.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type React from "react";
import type { JSX } from "react";
Expand All @@ -19,6 +20,7 @@ import { useAccountContext } from "../../../../core/account/provider.js";
export interface AccountNameProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children">,
Omit<ResolveNameOptions, "client" | "address"> {
asChild?: boolean;
/**
* A function used to transform (format) the name of the account.
* it should take in a string and output a string.
Expand Down Expand Up @@ -134,6 +136,7 @@ export function AccountName({
queryOptions,
loadingComponent,
fallbackComponent,
asChild,
...restProps
}: AccountNameProps) {
const { address, client } = useAccountContext();
Expand Down Expand Up @@ -177,5 +180,6 @@ export function AccountName({
return fallbackComponent || null;
}

return <span {...restProps}>{nameQuery.data}</span>;
const Comp = asChild ? Slot.Root : "span";
return <Comp {...restProps}>{nameQuery.data}</Comp>;
}
6 changes: 5 additions & 1 deletion packages/thirdweb/src/react/web/ui/prebuilt/Chain/icon.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type { JSX } from "react";
import type { Chain } from "../../../../../chains/types.js";
Expand All @@ -16,6 +17,7 @@ import { useChainContext } from "./provider.js";
*/
export interface ChainIconProps
extends Omit<React.ImgHTMLAttributes<HTMLImageElement>, "src"> {
asChild?: boolean;
/**
* You need a ThirdwebClient to resolve the icon which is hosted on IPFS.
* (since most chain icons are hosted on IPFS, loading them via thirdweb gateway will ensure better performance)
Expand Down Expand Up @@ -119,6 +121,7 @@ export function ChainIcon({
fallbackComponent,
queryOptions,
client,
asChild,
...restProps
}: ChainIconProps) {
const { chain } = useChainContext();
Expand All @@ -136,7 +139,8 @@ export function ChainIcon({
return fallbackComponent || null;
}

return <img src={iconQuery.data} {...restProps} alt={restProps.alt} />;
const Comp = asChild ? Slot.Root : "img";
return <Comp src={iconQuery.data} {...restProps} alt={restProps.alt} />;
}

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/thirdweb/src/react/web/ui/prebuilt/Chain/name.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type React from "react";
import type { JSX } from "react";
Expand All @@ -15,6 +16,7 @@ import { useChainContext } from "./provider.js";
*/
export interface ChainNameProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
asChild?: boolean;
/**
* This prop can be a string or a (async) function that resolves to a string, representing the name of the chain
* This is particularly useful if you already have a way to fetch the chain name.
Expand Down Expand Up @@ -153,6 +155,7 @@ export function ChainName({
loadingComponent,
fallbackComponent,
queryOptions,
asChild,
...restProps
}: ChainNameProps) {
const { chain } = useChainContext();
Expand All @@ -172,7 +175,8 @@ export function ChainName({

const displayValue = formatFn ? formatFn(nameQuery.data) : nameQuery.data;

return <span {...restProps}>{displayValue}</span>;
const Comp = asChild ? Slot.Root : "span";
return <Comp {...restProps}>{displayValue}</Comp>;
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import * as Slot from "@radix-ui/react-slot";
import { type UseQueryOptions, useQuery } from "@tanstack/react-query";
import type { JSX } from "react";
import type { ThirdwebContract } from "../../../../../contract/contract.js";
Expand All @@ -9,6 +10,7 @@ import { getNFTInfo } from "./utils.js";

export interface NFTDescriptionProps
extends Omit<React.HTMLAttributes<HTMLSpanElement>, "children"> {
asChild?: boolean;
loadingComponent?: JSX.Element;
fallbackComponent?: JSX.Element;
/**
Expand Down Expand Up @@ -88,6 +90,7 @@ export function NFTDescription({
fallbackComponent,
queryOptions,
descriptionResolver,
asChild,
...restProps
}: NFTDescriptionProps) {
const { contract, tokenId } = useNFTContext();
Expand Down Expand Up @@ -119,7 +122,8 @@ export function NFTDescription({
return fallbackComponent || null;
}

return <span {...restProps}>{descQuery.data}</span>;
const Comp = asChild ? Slot.Root : "span";
return <Comp {...restProps}>{descQuery.data}</Comp>;
}

/**
Expand Down
Loading

0 comments on commit 7bda6cd

Please sign in to comment.