Skip to content

PaymentGate

Provides the UI shell for collecting payment during booking. The actual Stripe Elements integration is injected via a render prop, allowing flexibility in payment method support (card, Apple Pay, Google Pay). The mode prop selects between full prepayment, deposit, and no-show-hold copy — for deposits, the component also displays the balance due at the appointment when totalPriceCents is supplied.

Terminal window
npx thebookingkit add payment-gate
import { PaymentGate } from "@/components/payment-gate";
import { PaymentElement, useStripe } from "@stripe/react-stripe-js";
export function BookingPayment({ clientSecret }: { clientSecret: string }) {
const stripe = useStripe();
const handlePaymentSuccess = async () => {
const { error } = await stripe!.confirmPayment({
elements,
redirect: "if_required",
});
if (!error) router.push("/confirmation");
};
return (
<PaymentGate
amountCents={2500}
currency="USD"
clientSecret={clientSecret}
onPaymentSuccess={handlePaymentSuccess}
renderPaymentElement={() => <PaymentElement />}
/>
);
}

When the event type has a deposit configured, set mode="deposit" and pass totalPriceCents so the customer sees the remaining balance:

<PaymentGate
mode="deposit"
amountCents={2500}
totalPriceCents={10000}
currency="USD"
clientSecret={clientSecret}
onPaymentSuccess={handlePaymentSuccess}
renderPaymentElement={() => <PaymentElement />}
/>

The header shows “Pay deposit” and the helper text reads “Balance of $75.00 due at the appointment.”

<PaymentGate
mode="no_show_hold"
amountCents={5000}
currency="USD"
clientSecret={clientSecret}
onPaymentSuccess={handlePaymentSuccess}
renderPaymentElement={() => <PaymentElement />}
/>
export type PaymentGateMode = "prepayment" | "deposit" | "no_show_hold";
export interface PaymentGateProps {
/** Amount in smallest currency unit (e.g., cents) */
amountCents: number;
/** ISO 4217 currency code (e.g., "USD") */
currency: string;
/** Stripe client secret for the PaymentIntent */
clientSecret: string;
/**
* Type of payment being collected. Affects header copy and the submit label.
* Defaults to "prepayment" for backwards compatibility.
*/
mode?: PaymentGateMode;
/**
* Total event price in cents. When `mode === "deposit"`, used to display
* the remaining balance ("Balance of $X due at the appointment").
*/
totalPriceCents?: number;
/** Called when payment succeeds */
onPaymentSuccess: (paymentIntentId: string) => void;
/** Called when payment fails */
onPaymentError?: (error: string) => void;
/** Called when the user cancels/goes back */
onCancel?: () => void;
/** Whether the payment is currently processing */
isProcessing?: boolean;
/** Label for the pay button (default: "Pay {amount}") */
submitLabel?: string;
/** Additional CSS class name */
className?: string;
/** Inline styles */
style?: React.CSSProperties;
/** Render prop for the payment form element. */
renderPaymentElement?: () => React.ReactNode;
}

The component source is fetched from the docs registry at install time. Run npx thebookingkit add payment-gate to copy it into your project, or browse the latest source on GitHub.