Skip to content

Commit ed5ecdc

Browse files
committed
[PRO-144] SDK: Update in-app wallet icon in wide connect ui
1 parent 759f41b commit ed5ecdc

File tree

8 files changed

+399
-20
lines changed

8 files changed

+399
-20
lines changed

.changeset/sixty-clubs-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"thirdweb": patch
3+
---
4+
5+
Update in-app wallet icon in wide connect ui

packages/thirdweb/src/react/web/ui/ConnectWallet/WalletEntryButton.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { Skeleton } from "../components/Skeleton.js";
1717
import { Text } from "../components/text.js";
1818
import { WalletImage } from "../components/WalletImage.js";
1919
import { StyledButton } from "../design-system/elements.js";
20+
import { InAppWalletIcon } from "./in-app-wallet-icon.js";
2021
import type { ConnectLocale } from "./locale/types.js";
2122

2223
/**
@@ -70,6 +71,11 @@ export function WalletEntryButton(props: {
7071
src={iconOverride}
7172
width={`${iconSize.xl}`}
7273
/>
74+
) : wallet.id === "inApp" ? (
75+
<InAppWalletIcon
76+
client={props.client}
77+
wallet={wallet as Wallet<"inApp">}
78+
/>
7379
) : (
7480
<WalletImage client={props.client} id={walletId} size={iconSize.xl} />
7581
)}
Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,23 @@
11
import type { IconFC } from "./types.js";
22

3-
/**
4-
* @internal
5-
*/
63
export const EmailIcon: IconFC = (props) => {
74
return (
85
<svg
9-
fill="none"
6+
xmlns="http://www.w3.org/2000/svg"
7+
width={props.size}
108
height={props.size}
9+
viewBox="0 0 24 24"
1110
role="presentation"
12-
viewBox="0 0 16 16"
13-
width={props.size}
14-
xmlns="http://www.w3.org/2000/svg"
11+
fill="none"
12+
stroke="currentColor"
13+
strokeWidth="2"
14+
strokeLinecap="round"
15+
strokeLinejoin="round"
16+
className="lucide lucide-mail-icon lucide-mail"
17+
style={{ color: props.color }}
1518
>
16-
<path
17-
d="M13.3335 2.6665H2.66683C1.93045 2.6665 1.3335 3.26346 1.3335 3.99984V11.9998C1.3335 12.7362 1.93045 13.3332 2.66683 13.3332H13.3335C14.0699 13.3332 14.6668 12.7362 14.6668 11.9998V3.99984C14.6668 3.26346 14.0699 2.6665 13.3335 2.6665Z"
18-
stroke={props.color ?? "currentColor"}
19-
strokeLinecap="round"
20-
strokeLinejoin="round"
21-
/>
22-
<path
23-
d="M14.6668 4.6665L8.68683 8.4665C8.48101 8.59545 8.24304 8.66384 8.00016 8.66384C7.75728 8.66384 7.51931 8.59545 7.3135 8.4665L1.3335 4.6665"
24-
stroke={props.color ?? "currentColor"}
25-
strokeLinecap="round"
26-
strokeLinejoin="round"
27-
/>
19+
<path d="m22 7-8.991 5.727a2 2 0 0 1-2.009 0L2 7" />
20+
<rect x="2" y="4" width="20" height="16" rx="2" />
2821
</svg>
2922
);
3023
};

packages/thirdweb/src/react/web/ui/ConnectWallet/icons/WalletDotIcon.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const WalletDotIcon: IconFC = (props) => {
1111
viewBox="0 0 18 18"
1212
width={props.size}
1313
height={props.size}
14+
style={{ color: props.color }}
1415
role="presentation"
1516
>
1617
<path
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
"use client";
2+
import type { ThirdwebClient } from "../../../../client/client.js";
3+
import type { Wallet } from "../../../../wallets/interfaces/wallet.js";
4+
import type { AuthOption } from "../../../../wallets/types.js";
5+
import { useCustomTheme } from "../../../core/design-system/CustomThemeProvider.js";
6+
import {
7+
iconSize,
8+
radius,
9+
spacing,
10+
} from "../../../core/design-system/index.js";
11+
import { socialIcons } from "../../../core/utils/walletIcon.js";
12+
import { defaultAuthOptions } from "../../wallets/shared/ConnectWalletSocialOptions.js";
13+
import { Img } from "../components/Img.js";
14+
import { EmailIcon } from "./icons/EmailIcon.js";
15+
import { FingerPrintIcon } from "./icons/FingerPrintIcon.js";
16+
import { GuestIcon } from "./icons/GuestIcon.js";
17+
import { PhoneIcon } from "./icons/PhoneIcon.js";
18+
19+
export function InAppWalletIcon(props: {
20+
client: ThirdwebClient;
21+
wallet: Wallet<"inApp">;
22+
}) {
23+
const enabledAuthMethods = (
24+
props.wallet.getConfig()?.auth?.options || defaultAuthOptions
25+
).sort((a, b) => {
26+
if (a in socialIcons && !(b in socialIcons)) {
27+
return -1;
28+
}
29+
if (!(a in socialIcons) && b in socialIcons) {
30+
return 1;
31+
}
32+
return 0;
33+
});
34+
const theme = useCustomTheme();
35+
36+
const firstMethod = enabledAuthMethods[0];
37+
const secondMethod = enabledAuthMethods[1];
38+
const thirdMethod = enabledAuthMethods[2];
39+
const fourthMethod = enabledAuthMethods[3];
40+
41+
const offset = "3.5px";
42+
const offset2 = "6px";
43+
const smallIconSize = "20";
44+
const extraIconSize = "12";
45+
46+
if (firstMethod && secondMethod) {
47+
return (
48+
<div
49+
style={{
50+
width: `${iconSize.xl}px`,
51+
height: `${iconSize.xl}px`,
52+
position: "relative",
53+
gap: spacing["3xs"],
54+
border: `1px solid ${theme.colors.borderColor}`,
55+
borderRadius: radius.md,
56+
backgroundColor: theme.colors.tertiaryBg,
57+
}}
58+
>
59+
<div
60+
style={{
61+
position: "absolute",
62+
top: offset,
63+
left: offset,
64+
display: "flex",
65+
}}
66+
>
67+
<AuthOptionIcon
68+
authOption={firstMethod}
69+
client={props.client}
70+
size={smallIconSize}
71+
/>
72+
</div>
73+
74+
<div
75+
style={{
76+
position: "absolute",
77+
bottom: offset,
78+
right: offset,
79+
display: "flex",
80+
}}
81+
>
82+
<AuthOptionIcon
83+
authOption={secondMethod}
84+
client={props.client}
85+
size={smallIconSize}
86+
/>
87+
</div>
88+
89+
<div>
90+
{thirdMethod && (
91+
<div
92+
style={{
93+
position: "absolute",
94+
top: offset2,
95+
right: offset2,
96+
display: "flex",
97+
}}
98+
>
99+
<AuthOptionIcon
100+
authOption={thirdMethod}
101+
client={props.client}
102+
size={extraIconSize}
103+
/>
104+
</div>
105+
)}
106+
107+
{fourthMethod && (
108+
<div
109+
style={{
110+
position: "absolute",
111+
bottom: offset2,
112+
left: offset2,
113+
display: "flex",
114+
}}
115+
>
116+
<AuthOptionIcon
117+
authOption={fourthMethod}
118+
client={props.client}
119+
size={extraIconSize}
120+
/>
121+
</div>
122+
)}
123+
</div>
124+
</div>
125+
);
126+
}
127+
128+
if (firstMethod) {
129+
return (
130+
<div
131+
style={{
132+
width: `${iconSize.xl}px`,
133+
height: `${iconSize.xl}px`,
134+
display: "flex",
135+
justifyContent: "center",
136+
alignItems: "center",
137+
border: `1px solid ${theme.colors.borderColor}`,
138+
borderRadius: radius.md,
139+
backgroundColor: theme.colors.tertiaryBg,
140+
}}
141+
>
142+
<AuthOptionIcon
143+
authOption={firstMethod}
144+
client={props.client}
145+
key={firstMethod}
146+
size={iconSize.lg}
147+
/>
148+
</div>
149+
);
150+
}
151+
152+
return null;
153+
}
154+
155+
function AuthOptionIcon(props: {
156+
authOption: AuthOption;
157+
client: ThirdwebClient;
158+
size: string;
159+
}) {
160+
const theme = useCustomTheme();
161+
if (props.authOption in socialIcons) {
162+
const icon = socialIcons[props.authOption as keyof typeof socialIcons];
163+
return (
164+
<Img
165+
src={icon}
166+
width={props.size}
167+
height={props.size}
168+
client={props.client}
169+
/>
170+
);
171+
}
172+
173+
if (props.authOption === "phone") {
174+
return <PhoneIcon size={props.size} color={theme.colors.secondaryText} />;
175+
}
176+
177+
if (props.authOption === "email") {
178+
return <EmailIcon size={props.size} color={theme.colors.secondaryText} />;
179+
}
180+
181+
if (props.authOption === "passkey") {
182+
return (
183+
<FingerPrintIcon size={props.size} color={theme.colors.secondaryText} />
184+
);
185+
}
186+
187+
if (props.authOption === "guest") {
188+
return <GuestIcon size={props.size} color={theme.colors.secondaryText} />;
189+
}
190+
191+
return null;
192+
}

packages/thirdweb/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export type ConnectWalletSelectUIState =
6161
};
6262
};
6363

64-
const defaultAuthOptions: AuthOption[] = [
64+
export const defaultAuthOptions: AuthOption[] = [
6565
"email",
6666
"phone",
6767
"google",

packages/thirdweb/src/stories/ConnectEmbed.stories.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { Meta } from "@storybook/react";
22
import { ConnectButton } from "../react/web/ui/ConnectWallet/ConnectButton.js";
33
import { ConnectEmbed } from "../react/web/ui/ConnectWallet/Modal/ConnectEmbed.js";
4+
import { createWallet } from "../wallets/create-wallet.js";
45
import { ecosystemWallet } from "../wallets/in-app/web/ecosystem.js";
56
import { inAppWallet } from "../wallets/in-app/web/in-app.js";
67
import { storyClient } from "./utils.js";
@@ -110,6 +111,24 @@ export function AllInAppWalletAuthMethods() {
110111
);
111112
}
112113

114+
export function ConfiguredInAppWalletWideModal() {
115+
return (
116+
<ConnectEmbed
117+
client={storyClient}
118+
className="foo-bar"
119+
modalSize="wide"
120+
wallets={[
121+
createWallet("io.metamask"),
122+
inAppWallet({
123+
auth: {
124+
options: ["google", "github", "email"],
125+
},
126+
}),
127+
]}
128+
/>
129+
);
130+
}
131+
113132
export function EcosystemWallet() {
114133
return (
115134
<ConnectEmbed

0 commit comments

Comments
 (0)