From f757e6084648b6b6e5879abeab30954753a1020d Mon Sep 17 00:00:00 2001 From: MananTank Date: Thu, 23 Oct 2025 23:21:57 +0000 Subject: [PATCH] [MNY-237] SDK: Update theme colors, minor UI tweaks (#8305) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ## PR-Codex overview This PR focuses on updating theme colors and making minor UI tweaks across various React components in the `thirdweb` package. ### Detailed summary - Updated `weight` from `600` to `500` in multiple components' `Text`. - Adjusted `border` styles in `Container` components. - Modified padding and margin in several layout elements. - Enhanced UI elements with consistent `letterSpacing` and `fontSize`. - Added new theme stories for `darkThemeObj` and `lightThemeObj`. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` ## Summary by CodeRabbit - **New Features** - Added Storybook theme showcase displaying color tokens and design system palette - **Bug Fixes** - Improved loading skeleton UI with better scrollable layout and visual consistency - **Style** - Refactored theme system with explicit color objects - Updated button styling with adjusted border radius and padding - Refined typography (font weights) across UI components - Adjusted layout spacing and padding throughout Bridge and wallet components - Increased QR code size for improved visibility - **Chores** - Added changeset documentation for patch release --- .changeset/wise-actors-attack.md | 5 + .../src/react/core/design-system/index.ts | 172 +++++++---------- .../FiatProviderSelection.tsx | 7 +- .../payment-selection/PaymentSelection.tsx | 2 +- .../payment-selection/TokenSelection.tsx | 174 +++++++++--------- .../payment-selection/WalletFiatSelection.tsx | 167 +++++++---------- .../ui/ConnectWallet/WalletEntryButton.tsx | 2 +- .../web/ui/ConnectWallet/WalletSelector.tsx | 4 +- .../ui/ConnectWallet/screens/ReceiveFunds.tsx | 5 +- .../react/web/ui/components/modalElements.tsx | 3 +- .../web/wallets/shared/ConnectingScreen.tsx | 2 +- .../thirdweb/src/stories/theme.stories.tsx | 165 +++++++++++++++++ 12 files changed, 404 insertions(+), 304 deletions(-) create mode 100644 .changeset/wise-actors-attack.md create mode 100644 packages/thirdweb/src/stories/theme.stories.tsx diff --git a/.changeset/wise-actors-attack.md b/.changeset/wise-actors-attack.md new file mode 100644 index 00000000000..9ac062a8e66 --- /dev/null +++ b/.changeset/wise-actors-attack.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Update theme colors and minor UI tweaks in React Components diff --git a/packages/thirdweb/src/react/core/design-system/index.ts b/packages/thirdweb/src/react/core/design-system/index.ts index 64ca0076207..363a6843520 100644 --- a/packages/thirdweb/src/react/core/design-system/index.ts +++ b/packages/thirdweb/src/react/core/design-system/index.ts @@ -1,48 +1,3 @@ -type ThemeColors = { - base1: string; - base2: string; - base3: string; - base4: string; - primaryText: string; - secondaryText: string; - danger: string; - success: string; - overlay: string; - accentText: string; - accentBg: string; - textOnAccent: string; -}; - -const darkColors = { - accentBg: "hsl(216 100% 50%)", - accentText: "#3385FF", - base1: "hsl(230 11.63% 8.43%)", - base2: "hsl(230 11.63% 12%)", - base3: "hsl(230 11.63% 15%)", - base4: "hsl(230 11.63% 17%)", - danger: "#e5484D", - overlay: "rgba(0, 0, 0, 0.7)", - primaryText: "#eeeef0", - secondaryText: "#7c7a85", - success: "#30A46C", - textOnAccent: "#eeeef0", -} as const satisfies ThemeColors; - -const lightColors = { - accentBg: "hsl(216 100% 50%)", - accentText: "#3385FF", - base1: "#fdfcfd", - base2: "#f2eff3", - base3: "#e3dfe6", - base4: "#dbd8e0", - danger: "#e5484D", - overlay: "rgba(0, 0, 0, 0.7)", - primaryText: "#211f26", - secondaryText: "#6f6d78", - success: "#30A46C", - textOnAccent: "#fdfcfd", -} as const satisfies ThemeColors; - /** * @theme */ @@ -95,64 +50,77 @@ export type Theme = { fontFamily: string; }; -/** - * @internal - */ -function createThemeObj(type: "dark" | "light", colors: ThemeColors): Theme { - return { - colors: { - accentButtonBg: colors.accentBg, - accentButtonText: colors.textOnAccent, - accentText: colors.accentText, - - borderColor: colors.base4, - - connectedButtonBg: colors.base1, - connectedButtonBgHover: colors.base2, - - danger: colors.danger, - - inputAutofillBg: colors.base1, - - modalBg: colors.base1, - - modalOverlayBg: colors.overlay, - - primaryButtonBg: colors.primaryText, - primaryButtonText: colors.base1, - primaryText: colors.primaryText, - scrollbarBg: colors.base2, - - secondaryButtonBg: colors.base3, - secondaryButtonHoverBg: colors.base4, - secondaryButtonText: colors.primaryText, - - secondaryIconColor: colors.secondaryText, - secondaryIconHoverBg: colors.base3, - secondaryIconHoverColor: colors.primaryText, - secondaryText: colors.secondaryText, - selectedTextBg: colors.primaryText, - - selectedTextColor: colors.base1, - - separatorLine: colors.base4, - skeletonBg: colors.base4, - success: colors.success, - tertiaryBg: colors.base2, - - tooltipBg: colors.primaryText, - tooltipText: colors.base1, - }, - fontFamily: "inherit", - type, - }; -} +export const darkThemeObj: Theme = { + type: "dark", + colors: { + accentButtonBg: "hsl(221 83% 54%)", + accentButtonText: "hsl(0 0% 100%)", + accentText: "hsl(209.61deg 100% 65.31%)", + borderColor: "hsl(0 0% 15%)", + connectedButtonBg: "hsl(0 0% 3.92%)", + connectedButtonBgHover: "hsl(0 0% 11%)", + danger: "hsl(360 72% 55%)", + inputAutofillBg: "hsl(0 0% 11%)", + modalBg: "hsl(0 0% 3.92%)", + primaryButtonBg: "hsl(0 0% 100%)", + primaryButtonText: "hsl(0 0% 0%)", + primaryText: "hsl(0 0% 98%)", + scrollbarBg: "hsl(0 0% 11%)", + secondaryButtonBg: "hsl(0 0% 9%)", + modalOverlayBg: "rgba(0, 0, 0, 0.7)", + secondaryButtonHoverBg: "hsl(0 0% 9%/80%)", + secondaryButtonText: "hsl(0 0% 98%)", + secondaryIconColor: "hsl(0 0% 63%)", + secondaryIconHoverBg: "hsl(0 0% 11%)", + secondaryIconHoverColor: "hsl(0 0% 98%)", + secondaryText: "hsl(0 0% 63%)", + selectedTextBg: "hsl(0 0% 100%)", + selectedTextColor: "hsl(0 0% 0%)", + separatorLine: "hsl(0 0% 15%)", + skeletonBg: "hsl(0 0% 12%)", + success: "hsl(142 75% 50%)", + tertiaryBg: "hsl(0 0% 11%/50%)", + tooltipBg: "hsl(0 0% 11%)", + tooltipText: "hsl(0 0% 98%)", + }, + fontFamily: "inherit", +}; -export const darkThemeObj = /* @__PURE__ */ createThemeObj("dark", darkColors); -export const lightThemeObj = /* @__PURE__ */ createThemeObj( - "light", - lightColors, -); +export const lightThemeObj: Theme = { + type: "light", + colors: { + accentButtonBg: "hsl(221 83% 54%)", + accentButtonText: "hsl(0 0% 100%)", + accentText: "hsl(211.23deg 100% 44.47%)", + borderColor: "hsl(0 0% 85%)", + connectedButtonBg: "hsl(0 0% 100%)", + connectedButtonBgHover: "hsl(0 0% 93%)", + danger: "hsl(360 72% 60%)", + inputAutofillBg: "hsl(0 0% 93%)", + modalBg: "hsl(0 0% 100%)", + primaryButtonBg: "hsl(0 0% 4%)", + primaryButtonText: "hsl(0 0% 100%)", + primaryText: "hsl(0 0% 4%)", + scrollbarBg: "hsl(0 0% 93%)", + secondaryButtonBg: "hsl(0 0% 93%)", + modalOverlayBg: "rgba(0, 0, 0, 0.7)", + secondaryButtonHoverBg: "hsl(0 0% 93%/80%)", + secondaryButtonText: "hsl(0 0% 4%)", + secondaryIconColor: "hsl(0 0% 40%)", + secondaryIconHoverBg: "hsl(0 0% 93%)", + secondaryIconHoverColor: "hsl(0 0% 4%)", + secondaryText: "hsl(0 0% 40%)", + selectedTextBg: "hsl(0 0% 4%)", + selectedTextColor: "hsl(0 0% 100%)", + separatorLine: "hsl(0 0% 85%)", + skeletonBg: "hsl(0 0% 85%)", + success: "hsl(142.09 70.56% 35.29%)", + tertiaryBg: "hsl(0 0% 93%/70%)", + tooltipBg: "hsl(0 0% 100%)", + tooltipText: "hsl(0 0% 4%)", + }, + fontFamily: "inherit", +}; /** * @theme diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx index 84e763f986e..1cbe3040fb0 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/FiatProviderSelection.tsx @@ -5,7 +5,6 @@ import type { SupportedFiatCurrency } from "../../../../../pay/convert/type.js"; import { checksumAddress } from "../../../../../utils/address.js"; import { formatNumber } from "../../../../../utils/formatNumber.js"; import { toTokens } from "../../../../../utils/units.js"; -import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; import { iconSize, radius, @@ -62,8 +61,6 @@ export function FiatProviderSelection({ currency, country, }: FiatProviderSelectionProps) { - const theme = useCustomTheme(); - // Fetch quotes for all providers const quoteQueries = useBuyWithFiatQuotesForProviders({ amount: toAmount || "0", @@ -122,9 +119,9 @@ export function FiatProviderSelection({ fullWidth onClick={() => onProviderSelected(provider.id)} style={{ - border: `1px solid ${theme.colors.borderColor}`, - borderRadius: radius.md, + borderRadius: radius.lg, textAlign: "left", + padding: `${spacing.md}`, }} variant="secondary" > diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx index d71fce89e2e..b6576eb7590 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/PaymentSelection.tsx @@ -269,7 +269,7 @@ export function PaymentSelection({ } return ( - + 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 8e6c268e71e..de2dfa41bb0 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 @@ -61,10 +61,8 @@ function PaymentMethodTokenRow({ onClick={() => onPaymentMethodSelected(paymentMethod)} style={{ backgroundColor: theme.colors.tertiaryBg, - border: `1px solid ${theme.colors.borderColor}`, - borderRadius: radius.md, - opacity: hasEnoughBalance ? 1 : 0.5, - padding: `${spacing.sm} ${spacing.md}`, + borderRadius: radius.lg, + padding: `${spacing.md} ${spacing.md}`, textAlign: "left", }} variant="secondary" @@ -134,71 +132,74 @@ export function TokenSelection({ if (paymentMethodsLoading) { return ( - <> - - Loading your tokens - - - - {/* Skeleton rows matching PaymentMethodTokenRow structure */} - {[1, 2, 3].map((i) => ( + + {/* Skeleton rows matching PaymentMethodTokenRow structure */} + {new Array(10).fill(0).map((_, i) => ( + + {/* Left side: Token icon and name skeleton */} - {/* Left side: Token icon and name skeleton */} - - {/* Token icon skeleton */} -
- - {/* Token name skeleton */} - - {/* Chain name skeleton */} - - + {/* Token icon skeleton */} +
+ + {/* Token name skeleton */} + + {/* Chain name skeleton */} + + - {/* Right side: Price and balance skeleton */} - - {/* Price amount skeleton */} - - {/* Balance skeleton */} - - - - + {/* Right side: Price and balance skeleton */} + + {/* Price amount skeleton */} + + {/* Balance skeleton */} + + + - ))} - - + + ))} + ); } @@ -221,35 +222,30 @@ export function TokenSelection({ } return ( - <> - - Your token balances - - - - {paymentMethods - .filter((method) => method.type === "wallet") - .map((method) => ( - - ))} - - + + {paymentMethods + .filter((method) => method.type === "wallet") + .map((method) => ( + + ))} + ); } diff --git a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx index 3768bf2818d..0c8244e5d8d 100644 --- a/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx +++ b/packages/thirdweb/src/react/web/ui/Bridge/payment-selection/WalletFiatSelection.tsx @@ -1,5 +1,5 @@ "use client"; -import { ChevronRightIcon, PlusIcon } from "@radix-ui/react-icons"; +import { PlusIcon } from "@radix-ui/react-icons"; import type { ThirdwebClient } from "../../../../../client/client.js"; import type { Wallet } from "../../../../../wallets/interfaces/wallet.js"; import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js"; @@ -12,7 +12,6 @@ import { CreditCardIcon } from "../../ConnectWallet/icons/CreditCardIcon.js"; import { WalletRow } from "../../ConnectWallet/screens/Buy/swap/WalletRow.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"; interface WalletFiatSelectionProps { @@ -35,56 +34,39 @@ export function WalletFiatSelection({ const theme = useCustomTheme(); return ( - <> + {paymentMethods.includes("crypto") && ( <> - {paymentMethods.length > 1 && ( - <> - - Pay with Crypto - - - - )} - {/* Connected Wallets */} {connectedWallets.length > 0 && ( - <> - - {connectedWallets.map((wallet) => { - const account = wallet.getAccount(); - if (!account?.address) { - return null; - } - return ( - - ); - })} - - - + + {connectedWallets.map((wallet) => { + const account = wallet.getAccount(); + if (!account?.address) { + return null; + } + return ( + + ); + })} + )} {/* Connect Another Wallet */} @@ -92,11 +74,9 @@ export function WalletFiatSelection({ fullWidth onClick={onConnectWallet} style={{ - backgroundColor: theme.colors.tertiaryBg, - border: `1px solid ${theme.colors.borderColor}`, borderRadius: radius.md, height: "auto", - padding: `${spacing.sm} ${spacing.md}`, + padding: `${spacing.md} ${spacing.md}`, textAlign: "left", }} variant="secondary" @@ -109,23 +89,22 @@ export function WalletFiatSelection({ - + Connect a Wallet @@ -138,49 +117,37 @@ export function WalletFiatSelection({ )} {paymentMethods.includes("card") && ( - <> - - - - Pay with Card - - - - - - + + )} - + ); } diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletEntryButton.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletEntryButton.tsx index fb0f4c02e63..54bf16365d4 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletEntryButton.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletEntryButton.tsx @@ -76,7 +76,7 @@ export function WalletEntryButton(props: { {nameOverride ? ( - + {nameOverride} ) : ( diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletSelector.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletSelector.tsx index 4bd732de3e2..35f25aee4fa 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletSelector.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/WalletSelector.tsx @@ -320,7 +320,7 @@ const WalletSelectorInner: React.FC = (props) => { bottomSection = ( <> - + {newToWallets} {continueAsGuest} @@ -705,7 +705,7 @@ const ShowAllWalletsIcon = /* @__PURE__ */ StyledDiv(() => { }, alignItems: "center", backgroundColor: theme.colors.tertiaryBg, - border: `2px solid ${theme.colors.borderColor}`, + border: `1px solid ${theme.colors.borderColor}`, borderRadius: radius.md, display: "grid", gap: spacing["4xs"], diff --git a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx index a07e5a5ecff..fc7301d6866 100644 --- a/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx +++ b/packages/thirdweb/src/react/web/ui/ConnectWallet/screens/ReceiveFunds.tsx @@ -52,7 +52,7 @@ export function ReceiveFunds(props: { ) } qrCodeUri={address} - size={310} + size={350} /> @@ -62,7 +62,7 @@ export function ReceiveFunds(props: { className="tw-copy-address-button" > - {shortenString(address || "")} + {shortenString(address || "", false)} diff --git a/packages/thirdweb/src/react/web/ui/components/modalElements.tsx b/packages/thirdweb/src/react/web/ui/components/modalElements.tsx index 43280327875..adad0316ddb 100644 --- a/packages/thirdweb/src/react/web/ui/components/modalElements.tsx +++ b/packages/thirdweb/src/react/web/ui/components/modalElements.tsx @@ -10,9 +10,10 @@ export const ModalTitle = /* @__PURE__ */ StyledH2((_) => { return { color: theme.colors.primaryText, fontSize: fontSize.lg, - fontWeight: 600, + fontWeight: 500, lineHeight: 1.3, margin: 0, + letterSpacing: "-0.025em", textAlign: "left", }; }); diff --git a/packages/thirdweb/src/react/web/wallets/shared/ConnectingScreen.tsx b/packages/thirdweb/src/react/web/wallets/shared/ConnectingScreen.tsx index 47bd841d68c..24d37455d7f 100644 --- a/packages/thirdweb/src/react/web/wallets/shared/ConnectingScreen.tsx +++ b/packages/thirdweb/src/react/web/wallets/shared/ConnectingScreen.tsx @@ -74,7 +74,7 @@ export const ConnectingScreen: React.FC<{ center color="primaryText" size="lg" - weight={600} + weight={500} className="tw-screen-title" data-status={props.errorConnecting ? "failed" : "in-progress"} > diff --git a/packages/thirdweb/src/stories/theme.stories.tsx b/packages/thirdweb/src/stories/theme.stories.tsx new file mode 100644 index 00000000000..7ff2cf08caf --- /dev/null +++ b/packages/thirdweb/src/stories/theme.stories.tsx @@ -0,0 +1,165 @@ +import type { Meta } from "@storybook/react-vite"; +import { + darkThemeObj, + lightThemeObj, + type Theme, +} from "../react/core/design-system/index.js"; +import { StyledDiv } from "../react/web/ui/design-system/elements.js"; + +const meta: Meta = { + title: "theme", +}; +export default meta; + +export function Dark() { + return ; +} + +export function Light() { + return ; +} + +function Variant(props: { theme: Theme }) { + return ( +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ border +
+ +
+ separatorLine +
+
+ ); +} + +function ColorPairTest(props: { + theme: Theme; + bg?: keyof Theme["colors"]; + text: keyof Theme["colors"]; + hoverBg?: keyof Theme["colors"]; + hoverText?: keyof Theme["colors"]; +}) { + return ( + + {[props.bg, props.hoverBg, props.text].filter(Boolean).join(", ")} + + ); +} +const HoverBg = StyledDiv( + (props: { + bg?: string; + hoverBg?: string; + text: string; + hoverText?: string; + }) => { + return { + backgroundColor: props.bg ?? "transparent", + padding: "20px", + borderRadius: "8px", + fontSize: "16px", + fontWeight: 400, + color: props.text, + "&:hover": props.hoverBg + ? { + backgroundColor: props.hoverBg, + } + : undefined, + }; + }, +);