[MNY-341] Payment Details UI improvements (#8576)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on improving the Payment Details UI for bridge widget components in the `thirdweb` package, enhancing layout, styling, and functionality. ### Detailed summary - Adjusted `padding` in `TokenBalanceRow.tsx`. - Replaced `OutlineWalletIcon` with a styled `Container` in `WalletRow.tsx`. - Updated `borderRadius` and `borderBottom` styles in `PaymentOverview.tsx`. - Enhanced `StepConnectorArrow` styles and added `iconSize` for `ChevronDownIcon`. - Modified `OutlineWalletIcon` definition to accept `size`, `color`, and `style` props. - Refactored `cryptoPaymentMethod` and `ethCryptoPaymentMethod` structures for clarity. - Updated `PaymentDetails.tsx` styles, including `gap`, `borderRadius`, and button styles. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved bridge payment details UI with enhanced spacing, borders, and styling * Updated wallet row display with better visual presentation when disconnected * Refined typography and color usage across payment interface components * Enhanced border radius and padding consistency throughout bridge widget <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"thirdweb": patch
|
||||
---
|
||||
|
||||
Payment Details UI improvements for bridge widget components
|
||||
@@ -33,7 +33,7 @@ export function TokenBalanceRow({
|
||||
style={{
|
||||
display: "flex",
|
||||
justifyContent: "space-between",
|
||||
padding: `${spacing.sm} ${spacing.md}`,
|
||||
padding: `${spacing.md} ${spacing.md}`,
|
||||
...style,
|
||||
}}
|
||||
variant="secondary"
|
||||
|
||||
@@ -4,7 +4,11 @@ import { defineChain } from "../../../../../chains/utils.js";
|
||||
import type { ThirdwebClient } from "../../../../../client/client.js";
|
||||
import type { SupportedFiatCurrency } from "../../../../../pay/convert/type.js";
|
||||
import { useCustomTheme } from "../../../../core/design-system/CustomThemeProvider.js";
|
||||
import { radius, spacing } from "../../../../core/design-system/index.js";
|
||||
import {
|
||||
iconSize,
|
||||
radius,
|
||||
spacing,
|
||||
} from "../../../../core/design-system/index.js";
|
||||
import { useChainsQuery } from "../../../../core/hooks/others/useChainQuery.js";
|
||||
import type { BridgePrepareResult } from "../../../../core/hooks/useBridgePrepare.js";
|
||||
import {
|
||||
@@ -306,12 +310,12 @@ export function PaymentDetails({
|
||||
|
||||
<Container
|
||||
flex="column"
|
||||
gap="sm"
|
||||
gap="md+"
|
||||
style={{
|
||||
backgroundColor: theme.colors.tertiaryBg,
|
||||
border: `1px solid ${theme.colors.borderColor}`,
|
||||
borderRadius: radius.md,
|
||||
padding: `${spacing.sm} ${spacing.md}`,
|
||||
borderRadius: radius.xl,
|
||||
padding: `${spacing.md} ${spacing.md}`,
|
||||
}}
|
||||
>
|
||||
{preparedQuote.steps.map((step, stepIndex) => (
|
||||
@@ -323,24 +327,24 @@ export function PaymentDetails({
|
||||
{/* Step Header */}
|
||||
<Container
|
||||
flex="row"
|
||||
gap="md"
|
||||
gap="sm"
|
||||
style={{ alignItems: "center" }}
|
||||
>
|
||||
<Container
|
||||
center="both"
|
||||
flex="row"
|
||||
style={{
|
||||
backgroundColor: theme.colors.accentButtonBg,
|
||||
borderRadius: "50%",
|
||||
color: theme.colors.accentButtonText,
|
||||
backgroundColor: theme.colors.modalBg,
|
||||
border: `1px solid ${theme.colors.borderColor}`,
|
||||
borderRadius: radius.full,
|
||||
color: theme.colors.secondaryText,
|
||||
flexShrink: 0,
|
||||
fontSize: "12px",
|
||||
fontWeight: "bold",
|
||||
height: "24px",
|
||||
width: "24px",
|
||||
height: `${iconSize.lg}px`,
|
||||
width: `${iconSize.lg}px`,
|
||||
}}
|
||||
>
|
||||
<Text color="accentButtonText" size="xs">
|
||||
<Text color="secondaryText" size="sm">
|
||||
{stepIndex + 1}
|
||||
</Text>
|
||||
</Container>
|
||||
@@ -352,7 +356,7 @@ export function PaymentDetails({
|
||||
style={{ flex: 1 }}
|
||||
>
|
||||
<Container flex="column" gap="3xs" style={{ flex: 1 }}>
|
||||
<Text color="primaryText" size="sm">
|
||||
<Text color="primaryText" size="sm" weight={500}>
|
||||
{step.destinationToken.chainId !==
|
||||
step.originToken.chainId ? (
|
||||
<>
|
||||
@@ -401,11 +405,16 @@ export function PaymentDetails({
|
||||
</Container>
|
||||
)}
|
||||
|
||||
<Spacer y="lg" />
|
||||
<Spacer y="md" />
|
||||
|
||||
{/* Action Buttons */}
|
||||
<Container flex="column" gap="sm">
|
||||
<Button fullWidth onClick={handleConfirm} variant="accent">
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={handleConfirm}
|
||||
variant="primary"
|
||||
style={{ borderRadius: radius.full }}
|
||||
>
|
||||
{confirmButtonLabel || "Confirm Payment"}
|
||||
</Button>
|
||||
</Container>
|
||||
|
||||
@@ -47,7 +47,7 @@ export function PaymentOverview(props: {
|
||||
flex="column"
|
||||
style={{
|
||||
border: `1px solid ${theme.colors.borderColor}`,
|
||||
borderRadius: radius.lg,
|
||||
borderRadius: radius.xl,
|
||||
}}
|
||||
>
|
||||
{sender && (
|
||||
@@ -55,9 +55,9 @@ export function PaymentOverview(props: {
|
||||
flex="row"
|
||||
gap="sm"
|
||||
px="md"
|
||||
py="sm"
|
||||
py="md"
|
||||
style={{
|
||||
borderBottom: `1px solid ${theme.colors.borderColor}`,
|
||||
borderBottom: `1px dashed ${theme.colors.borderColor}`,
|
||||
}}
|
||||
>
|
||||
<WalletRow
|
||||
@@ -88,7 +88,7 @@ export function PaymentOverview(props: {
|
||||
flex="row"
|
||||
gap="sm"
|
||||
px="md"
|
||||
py="sm"
|
||||
py="md"
|
||||
style={{ justifyContent: "space-between" }}
|
||||
>
|
||||
{/* left */}
|
||||
@@ -122,7 +122,7 @@ export function PaymentOverview(props: {
|
||||
flex="column"
|
||||
style={{
|
||||
border: `1px solid ${theme.colors.borderColor}`,
|
||||
borderRadius: radius.lg,
|
||||
borderRadius: radius.xl,
|
||||
}}
|
||||
>
|
||||
{isDifferentRecipient && (
|
||||
@@ -130,9 +130,9 @@ export function PaymentOverview(props: {
|
||||
flex="row"
|
||||
gap="sm"
|
||||
px="md"
|
||||
py="sm"
|
||||
py="md"
|
||||
style={{
|
||||
borderBottom: `1px solid ${theme.colors.borderColor}`,
|
||||
borderBottom: `1px dashed ${theme.colors.borderColor}`,
|
||||
}}
|
||||
>
|
||||
<WalletRow
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import type { IconFC } from "./types.js";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export const OutlineWalletIcon: IconFC = (props) => {
|
||||
export const OutlineWalletIcon = (props: {
|
||||
size?: string;
|
||||
color?: string;
|
||||
style?: React.CSSProperties;
|
||||
}) => {
|
||||
return (
|
||||
<svg
|
||||
fill="none"
|
||||
@@ -12,6 +14,7 @@ export const OutlineWalletIcon: IconFC = (props) => {
|
||||
viewBox="0 0 24 24"
|
||||
width={props.size}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={props.style}
|
||||
>
|
||||
<path
|
||||
d="M19 7V4C19 3.73478 18.8946 3.48043 18.7071 3.29289C18.5196 3.10536 18.2652 3 18 3H5C4.46957 3 3.96086 3.21071 3.58579 3.58579C3.21071 3.96086 3 4.46957 3 5C3 5.53043 3.21071 6.03914 3.58579 6.41421C3.96086 6.78929 4.46957 7 5 7H20C20.2652 7 20.5196 7.10536 20.7071 7.29289C20.8946 7.48043 21 7.73478 21 8V12M21 12H18C17.4696 12 16.9609 12.2107 16.5858 12.5858C16.2107 12.9609 16 13.4696 16 14C16 14.5304 16.2107 15.0391 16.5858 15.4142C16.9609 15.7893 17.4696 16 18 16H21C21.2652 16 21.5196 15.8946 21.7071 15.7071C21.8946 15.5196 22 15.2652 22 15V13C22 12.7348 21.8946 12.4804 21.7071 12.2929C21.5196 12.1054 21.2652 12 21 12Z"
|
||||
|
||||
+10
-7
@@ -1,5 +1,9 @@
|
||||
import { ChevronDownIcon } from "@radix-ui/react-icons";
|
||||
import { useCustomTheme } from "../../../../../../core/design-system/CustomThemeProvider.js";
|
||||
import {
|
||||
iconSize,
|
||||
radius,
|
||||
} from "../../../../../../core/design-system/index.js";
|
||||
import { Container } from "../../../../components/basic.js";
|
||||
|
||||
export function StepConnectorArrow() {
|
||||
@@ -9,8 +13,8 @@ export function StepConnectorArrow() {
|
||||
center="both"
|
||||
flex="row"
|
||||
style={{
|
||||
marginBottom: "-10px",
|
||||
marginTop: "-10px",
|
||||
marginBottom: "-12px",
|
||||
marginTop: "-12px",
|
||||
position: "relative",
|
||||
width: "100%",
|
||||
zIndex: 1000,
|
||||
@@ -18,17 +22,16 @@ export function StepConnectorArrow() {
|
||||
>
|
||||
<Container
|
||||
center="both"
|
||||
color="primaryText"
|
||||
color="secondaryText"
|
||||
flex="row"
|
||||
style={{
|
||||
backgroundColor: theme.colors.modalBg,
|
||||
border: `1px solid ${theme.colors.borderColor}`,
|
||||
borderRadius: "100%",
|
||||
height: "30px",
|
||||
width: "30px",
|
||||
borderRadius: radius.full,
|
||||
padding: "6px",
|
||||
}}
|
||||
>
|
||||
<ChevronDownIcon height={16} width={16} />
|
||||
<ChevronDownIcon height={iconSize["sm+"]} width={iconSize["sm+"]} />
|
||||
</Container>
|
||||
</Container>
|
||||
);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { isSmartWallet } from "../../../../../../../wallets/smart/index.js";
|
||||
import {
|
||||
fontSize,
|
||||
iconSize,
|
||||
radius,
|
||||
} from "../../../../../../core/design-system/index.js";
|
||||
import { useConnectedWallets } from "../../../../../../core/hooks/wallets/useConnectedWallets.js";
|
||||
import {
|
||||
@@ -58,7 +59,27 @@ export function WalletRow(props: {
|
||||
size={iconSizeValue}
|
||||
/>
|
||||
) : (
|
||||
<OutlineWalletIcon size={iconSizeValue} />
|
||||
<Container
|
||||
borderColor="borderColor"
|
||||
bg="modalBg"
|
||||
flex="row"
|
||||
center="both"
|
||||
style={{
|
||||
borderStyle: "solid",
|
||||
borderWidth: "1px",
|
||||
borderRadius: radius.full,
|
||||
width: `${iconSizeValue}px`,
|
||||
height: `${iconSizeValue}px`,
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<OutlineWalletIcon
|
||||
style={{
|
||||
position: "absolute",
|
||||
inset: "25%",
|
||||
}}
|
||||
/>
|
||||
</Container>
|
||||
)}
|
||||
<Container flex="column" gap="3xs">
|
||||
{props.label ? (
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { PaymentDetails } from "../../react/web/ui/Bridge/payment-details/PaymentDetails.js";
|
||||
import type { PaymentMethod } from "../../react/web/ui/Bridge/types.js";
|
||||
import { stringify } from "../../utils/json.js";
|
||||
import { ModalThemeWrapper, storyClient } from "../utils.js";
|
||||
import {
|
||||
buyWithApprovalQuote,
|
||||
@@ -22,41 +21,45 @@ const fiatPaymentMethod: PaymentMethod = {
|
||||
type: "fiat",
|
||||
};
|
||||
|
||||
const cryptoPaymentMethod: PaymentMethod = JSON.parse(
|
||||
stringify({
|
||||
balance: 100000000n,
|
||||
originToken: {
|
||||
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
chainId: 1,
|
||||
decimals: 6,
|
||||
iconUri:
|
||||
"https://assets.coingecko.com/coins/images/6319/large/USD_Coin_icon.png",
|
||||
name: "USD Coin",
|
||||
priceUsd: 1.0,
|
||||
symbol: "USDC",
|
||||
const cryptoPaymentMethod: PaymentMethod = {
|
||||
action: "buy",
|
||||
balance: 100000000n,
|
||||
hasEnoughBalance: true,
|
||||
originToken: {
|
||||
address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
chainId: 1,
|
||||
decimals: 6,
|
||||
iconUri:
|
||||
"https://assets.coingecko.com/coins/images/6319/large/USD_Coin_icon.png",
|
||||
name: "USD Coin",
|
||||
prices: {
|
||||
USD: 1.0,
|
||||
},
|
||||
payerWallet: STORY_MOCK_WALLET,
|
||||
type: "wallet",
|
||||
}),
|
||||
);
|
||||
symbol: "USDC",
|
||||
},
|
||||
payerWallet: STORY_MOCK_WALLET,
|
||||
type: "wallet",
|
||||
};
|
||||
|
||||
const ethCryptoPaymentMethod: PaymentMethod = JSON.parse(
|
||||
stringify({
|
||||
balance: 1000000000000000000n,
|
||||
originToken: {
|
||||
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
chainId: 1,
|
||||
decimals: 18,
|
||||
iconUri:
|
||||
"https://assets.coingecko.com/coins/images/6319/large/USD_Coin_icon.png",
|
||||
name: "Ethereum",
|
||||
priceUsd: 2500.0,
|
||||
symbol: "ETH",
|
||||
const ethCryptoPaymentMethod: PaymentMethod = {
|
||||
action: "buy",
|
||||
balance: 1000000000000000000n,
|
||||
hasEnoughBalance: true,
|
||||
originToken: {
|
||||
address: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
|
||||
chainId: 1,
|
||||
decimals: 18,
|
||||
iconUri:
|
||||
"https://assets.coingecko.com/coins/images/6319/large/USD_Coin_icon.png",
|
||||
name: "Ethereum",
|
||||
prices: {
|
||||
USD: 2500.0,
|
||||
},
|
||||
payerWallet: STORY_MOCK_WALLET,
|
||||
type: "wallet",
|
||||
}),
|
||||
);
|
||||
symbol: "ETH",
|
||||
},
|
||||
payerWallet: STORY_MOCK_WALLET,
|
||||
type: "wallet",
|
||||
};
|
||||
|
||||
const meta: Meta<typeof PaymentDetails> = {
|
||||
args: {
|
||||
|
||||
Reference in New Issue
Block a user