-
Notifications
You must be signed in to change notification settings - Fork 561
[SDK] Add enableCard prop to control fiat payment visibility #7465
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a6b3d14
0c4e326
e96f4fa
633856a
f1b894c
abd2103
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"thirdweb": patch | ||
--- | ||
|
||
Adds paymentMethods prop to BuyWidget, CheckoutWidget, and TransactionWidget to control available payment options. Accepts an array of "crypto" and/or "card" values. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,6 +13,7 @@ import { useId, useState } from "react"; | |
import type { Address } from "thirdweb"; | ||
import { defineChain } from "thirdweb/chains"; | ||
import { CustomRadioGroup } from "@/components/ui/CustomRadioGroup"; | ||
import { Checkbox } from "@/components/ui/checkbox"; | ||
import { Input } from "@/components/ui/input"; | ||
import { Label } from "@/components/ui/label"; | ||
import { cn } from "../../../../lib/utils"; | ||
|
@@ -53,6 +54,8 @@ export function LeftSection(props: { | |
const modalTitleIconId = useId(); | ||
const modalDescriptionId = useId(); | ||
const themeId = useId(); | ||
const cryptoPaymentId = useId(); | ||
const cardPaymentId = useId(); | ||
|
||
return ( | ||
<div className="flex flex-col gap-4"> | ||
|
@@ -161,6 +164,65 @@ export function LeftSection(props: { | |
/> | ||
</div> | ||
</div> | ||
|
||
{/* Payment Methods */} | ||
<div className="flex flex-col gap-3 pt-4"> | ||
<Label>Payment Methods</Label> | ||
<div className="flex gap-4"> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes( | ||
"crypto", | ||
)} | ||
id={cryptoPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
"crypto", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cryptoPaymentId}>Crypto</Label> | ||
</div> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes("card")} | ||
id={cardPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
"card", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cardPaymentId}>Card</Label> | ||
</div> | ||
</div> | ||
</div> | ||
Comment on lines
+168
to
+225
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Eliminate code duplication by extracting payment methods UI. The payment methods selection UI and logic is duplicated between the buy and checkout sections. This violates the DRY principle and makes maintenance harder. Consider extracting this into a reusable component: function PaymentMethodsSelector({
paymentMethods,
onPaymentMethodsChange,
cryptoId,
cardId
}: {
paymentMethods: ("crypto" | "card")[];
onPaymentMethodsChange: (methods: ("crypto" | "card")[]) => void;
cryptoId: string;
cardId: string;
}) {
const handleMethodChange = (method: "crypto" | "card", checked: boolean) => {
const newMethods = checked
? [...new Set([...paymentMethods, method])]
: paymentMethods.filter(m => m !== method);
onPaymentMethodsChange(newMethods);
};
return (
<div className="flex flex-col gap-3">
<Label>Payment Methods</Label>
<div className="flex gap-4">
<div className="flex items-center space-x-2">
<Checkbox
checked={paymentMethods.includes("crypto")}
id={cryptoId}
onCheckedChange={(checked) => handleMethodChange("crypto", !!checked)}
/>
<Label htmlFor={cryptoId}>Crypto</Label>
</div>
<div className="flex items-center space-x-2">
<Checkbox
checked={paymentMethods.includes("card")}
id={cardId}
onCheckedChange={(checked) => handleMethodChange("card", !!checked)}
/>
<Label htmlFor={cardId}>Card</Label>
</div>
</div>
</div>
);
} This approach also simplifies the checkbox change logic by using Also applies to: 315-372 🤖 Prompt for AI Agents
|
||
</div> | ||
</div> | ||
</div> | ||
|
@@ -249,6 +311,65 @@ export function LeftSection(props: { | |
/> | ||
</div> | ||
</div> | ||
|
||
{/* Payment Methods */} | ||
<div className="flex flex-col gap-3"> | ||
<Label>Payment Methods</Label> | ||
<div className="flex gap-4"> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes( | ||
"crypto", | ||
)} | ||
id={cryptoPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
"crypto", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "crypto", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cryptoPaymentId}>Crypto</Label> | ||
</div> | ||
<div className="flex items-center space-x-2"> | ||
<Checkbox | ||
checked={payOptions.paymentMethods.includes("card")} | ||
id={cardPaymentId} | ||
onCheckedChange={(checked) => { | ||
setOptions((v) => ({ | ||
...v, | ||
payOptions: { | ||
...v.payOptions, | ||
paymentMethods: checked | ||
? [ | ||
...v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
"card", | ||
] | ||
: v.payOptions.paymentMethods.filter( | ||
(m) => m !== "card", | ||
), | ||
}, | ||
})); | ||
}} | ||
/> | ||
<Label htmlFor={cardPaymentId}>Card</Label> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ID collision issue: Generate unique IDs for each section.
The same checkbox IDs (
cryptoPaymentId
,cardPaymentId
) are being reused in both the "buy" and "checkout" sections, which violates the requirement that DOM IDs be unique and could cause accessibility issues.Generate separate IDs for each section:
Then use the checkout-specific IDs in the checkout section (lines 324, 349).
📝 Committable suggestion
🤖 Prompt for AI Agents