I fallowing to documentation library:
https://github.com/stripe/react-stripe-js
I try set different layout from horizontal to vertical tabs
This part of code working:
const appearance = {
theme: "stripe",
};
When i switch theme then i see rendering new theme. But when i try pass options layout like this:
const options = {
clientSecret,
appearance,
layout: {
type: 'accordion',
defaultCollapsed: false,
radios: true,
spacedAccordionItems: true,
},
};
Then not working, not changes in fronted.
Here is full code example
'use client';
import { useState, useEffect } from "react";
import { loadStripe } from "@stripe/stripe-js";
import { Elements, PaymentElement, useStripe, useElements } from "@stripe/react-stripe-js";
// Load your Stripe public key
const stripePromise = loadStripe("pk_test ");
export default function PaymentPage() {
const [clientSecret, setClientSecret] = useState("");
useEffect(() => {
fetch("/api/create-payment-intent", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ amount: 5000, currency: "pln" }), // Adjust amount & currency
})
.then((res) => res.json())
.then((data) => setClientSecret(data.clientSecret));
}, []);
// Appearance and layout configuration
const appearance = {
theme: "stripe",
};
// Custom layout options for Accordion
const options = {
clientSecret,
appearance,
layout: {
type: 'accordion',
defaultCollapsed: false,
radios: true,
spacedAccordionItems: true,
},
};
return (
<div className="flex flex-col items-center gap-4 p-6">
{clientSecret ? (
<Elements stripe={stripePromise} options={options}>
<CheckoutForm />
</Elements>
) : (
<p>Loading payment options...</p>
)}
</div>
);
}
function CheckoutForm() {
const stripe = useStripe();
const elements = useElements();
const [loading, setLoading] = useState(false);
const [error, setError] = useState("");
const handleSubmit = async (event) => {
event.preventDefault();
if (!stripe || !elements) return;
setLoading(true);
const { error } = await stripe.confirmPayment({
elements,
confirmParams: { return_url: `${process.env.NEXT_PUBLIC_FRONTEND_URL}/success` },
redirect: "if_required",
});
if (error) {
setError(error.message);
setLoading(false);
} else {
alert("Payment successful!");
}
};
return (
<form onSubmit={handleSubmit} className="w-full max-w-full">
<PaymentElement />
{error && <p className="text-red-500">{error}</p>}
<button
type="submit"
disabled={!stripe || loading}
className="px-4 py-2 bg-blue-500 text-white rounded"
>
{loading ? "Processing..." : "Pay Now"}
</button>
</form>
);
}
The layout options
which you've defined should be passed into the PaymentElement component instead.
Example
const paymentElementOptions = {
layout: {
type: 'accordion',
defaultCollapsed: false,
radios: true,
spacedAccordionItems: true,
}
};
return (
<PaymentElement id="payment-element" options={paymentElementOptions} />
);
You can refer to the quickstart guide and refer to the JS doc for more details.