React components and hooks for Stripe.js and Elements payment processing integration
—
Individual card input elements for granular control over payment form layout. These elements provide fine-grained control over card data collection and can be used individually or together to create custom payment forms.
Complete card input element that collects card number, expiry date, and CVC in a single field.
/**
* Complete card input element collecting all card details
* @param props - Card element configuration props
* @returns JSX element for complete card input
*/
function CardElement(props: CardElementProps): JSX.Element;
interface CardElementProps extends ElementProps {
/** Configuration options for the Card Element */
options?: StripeCardElementOptions;
/** Triggered when data exposed by this Element is changed */
onChange?: (event: StripeCardElementChangeEvent) => any;
/** Triggered when the Element is fully rendered and can accept focus */
onReady?: (element: StripeCardElement) => any;
/** Triggered when the escape key is pressed within the Element */
onEscape?: () => any;
/** Triggered when there is a change to the available networks */
onNetworksChange?: (event: {elementType: 'card'}) => any;
/** Triggered when the Element fails to load */
onLoadError?: (event: {elementType: 'card'; error: StripeError}) => any;
}
interface StripeCardElementOptions {
/** Appearance and styling options */
style?: StripeElementStyle;
/** Placeholder text for the card input */
placeholder?: string;
/** Whether to hide the postal code field */
hidePostalCode?: boolean;
/** Whether to show the card brand icon */
iconStyle?: 'default' | 'solid';
/** Disabled state */
disabled?: boolean;
/** Default values */
value?: {
postalCode?: string;
};
}Usage Examples:
import React, { useState } from 'react';
import { CardElement, useStripe, useElements } from '@stripe/react-stripe-js';
const CardPaymentForm = () => {
const stripe = useStripe();
const elements = useElements();
const [cardComplete, setCardComplete] = useState(false);
const [cardError, setCardError] = useState(null);
const handleCardChange = (event) => {
setCardComplete(event.complete);
setCardError(event.error ? event.error.message : null);
};
const handleSubmit = async (event) => {
event.preventDefault();
if (!stripe || !elements) return;
const card = elements.getElement(CardElement);
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card: card,
billing_details: {
name: 'Jenny Rosen',
},
});
if (error) {
console.log('[error]', error);
} else {
console.log('[PaymentMethod]', paymentMethod);
}
};
return (
<form onSubmit={handleSubmit}>
<CardElement
options={{
style: {
base: {
fontSize: '16px',
color: '#424770',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#9e2146',
},
},
hidePostalCode: true
}}
onChange={handleCardChange}
onReady={() => console.log('CardElement ready')}
/>
{cardError && <div className="card-error">{cardError}</div>}
<button disabled={!stripe || !cardComplete}>
Pay
</button>
</form>
);
};Card number input element for collecting just the card number.
/**
* Card number input element
* @param props - Card number element configuration props
* @returns JSX element for card number input
*/
function CardNumberElement(props: CardNumberElementProps): JSX.Element;
interface CardNumberElementProps extends ElementProps {
/** Configuration options for the Card Number Element */
options?: StripeCardNumberElementOptions;
/** Triggered when data exposed by this Element is changed */
onChange?: (event: StripeCardNumberElementChangeEvent) => any;
/** Triggered when the Element is fully rendered and can accept focus */
onReady?: (element: StripeCardNumberElement) => any;
/** Triggered when the escape key is pressed within the Element */
onEscape?: () => any;
}
interface StripeCardNumberElementOptions {
/** Appearance and styling options */
style?: StripeElementStyle;
/** Placeholder text for the card number input */
placeholder?: string;
/** Whether to show the card brand icon */
showIcon?: boolean;
/** Icon style */
iconStyle?: 'default' | 'solid';
/** Disabled state */
disabled?: boolean;
}Card expiry date input element for collecting the expiration month and year.
/**
* Card expiry date input element
* @param props - Card expiry element configuration props
* @returns JSX element for card expiry input
*/
function CardExpiryElement(props: CardExpiryElementProps): JSX.Element;
interface CardExpiryElementProps extends ElementProps {
/** Configuration options for the Card Expiry Element */
options?: StripeCardExpiryElementOptions;
/** Triggered when data exposed by this Element is changed */
onChange?: (event: StripeCardExpiryElementChangeEvent) => any;
/** Triggered when the Element is fully rendered and can accept focus */
onReady?: (element: StripeCardExpiryElement) => any;
/** Triggered when the escape key is pressed within the Element */
onEscape?: () => any;
}
interface StripeCardExpiryElementOptions {
/** Appearance and styling options */
style?: StripeElementStyle;
/** Placeholder text for the expiry input */
placeholder?: string;
/** Disabled state */
disabled?: boolean;
}Card CVC/CVV input element for collecting the card verification code.
/**
* Card CVC input element
* @param props - Card CVC element configuration props
* @returns JSX element for card CVC input
*/
function CardCvcElement(props: CardCvcElementProps): JSX.Element;
interface CardCvcElementProps extends ElementProps {
/** Configuration options for the Card CVC Element */
options?: StripeCardCvcElementOptions;
/** Triggered when data exposed by this Element is changed */
onChange?: (event: StripeCardCvcElementChangeEvent) => any;
/** Triggered when the Element is fully rendered and can accept focus */
onReady?: (element: StripeCardCvcElement) => any;
/** Triggered when the escape key is pressed within the Element */
onEscape?: () => any;
}
interface StripeCardCvcElementOptions {
/** Appearance and styling options */
style?: StripeElementStyle;
/** Placeholder text for the CVC input */
placeholder?: string;
/** Disabled state */
disabled?: boolean;
}Multi-Element Usage Example:
import React, { useState } from 'react';
import {
CardNumberElement,
CardExpiryElement,
CardCvcElement,
useStripe,
useElements
} from '@stripe/react-stripe-js';
const SplitCardForm = () => {
const stripe = useStripe();
const elements = useElements();
const [cardState, setCardState] = useState({
number: { complete: false, error: null },
expiry: { complete: false, error: null },
cvc: { complete: false, error: null }
});
const handleCardChange = (field) => (event) => {
setCardState(prev => ({
...prev,
[field]: {
complete: event.complete,
error: event.error
}
}));
};
const isFormComplete = Object.values(cardState).every(field => field.complete);
const handleSubmit = async (event) => {
event.preventDefault();
if (!stripe || !elements) return;
const cardNumber = elements.getElement(CardNumberElement);
const { error, paymentMethod } = await stripe.createPaymentMethod({
type: 'card',
card: cardNumber,
});
if (error) {
console.log('Payment failed:', error);
} else {
console.log('Payment method created:', paymentMethod);
}
};
const elementOptions = {
style: {
base: {
fontSize: '18px',
color: '#424770',
letterSpacing: '0.025em',
fontFamily: 'Source Code Pro, monospace',
'::placeholder': {
color: '#aab7c4',
},
},
invalid: {
color: '#9e2146',
},
},
};
return (
<form onSubmit={handleSubmit} className="split-card-form">
<div className="card-row">
<div className="card-number">
<label>Card Number</label>
<CardNumberElement
options={elementOptions}
onChange={handleCardChange('number')}
/>
{cardState.number.error && (
<div className="error">{cardState.number.error.message}</div>
)}
</div>
</div>
<div className="card-row">
<div className="card-expiry">
<label>Expiry Date</label>
<CardExpiryElement
options={elementOptions}
onChange={handleCardChange('expiry')}
/>
{cardState.expiry.error && (
<div className="error">{cardState.expiry.error.message}</div>
)}
</div>
<div className="card-cvc">
<label>CVC</label>
<CardCvcElement
options={elementOptions}
onChange={handleCardChange('cvc')}
/>
{cardState.cvc.error && (
<div className="error">{cardState.cvc.error.message}</div>
)}
</div>
</div>
<button disabled={!stripe || !isFormComplete}>
Pay Now
</button>
</form>
);
};interface StripeCardElementChangeEvent {
elementType: 'card' | 'cardNumber' | 'cardExpiry' | 'cardCvc';
empty: boolean;
complete: boolean;
error?: StripeError;
value?: {
postalCode?: string;
};
brand?: string;
}
interface StripeCardNumberElementChangeEvent extends StripeCardElementChangeEvent {
elementType: 'cardNumber';
brand: 'visa' | 'mastercard' | 'amex' | 'discover' | 'diners' | 'jcb' | 'unionpay' | 'unknown';
}
interface StripeCardExpiryElementChangeEvent extends StripeCardElementChangeEvent {
elementType: 'cardExpiry';
}
interface StripeCardCvcElementChangeEvent extends StripeCardElementChangeEvent {
elementType: 'cardCvc';
}interface StripeElementStyle {
base?: StripeElementStyleVariant;
complete?: StripeElementStyleVariant;
empty?: StripeElementStyleVariant;
invalid?: StripeElementStyleVariant;
}
interface StripeElementStyleVariant {
color?: string;
fontFamily?: string;
fontSize?: string;
fontSmoothing?: string;
fontStyle?: string;
fontVariant?: string;
fontWeight?: string;
iconColor?: string;
lineHeight?: string;
letterSpacing?: string;
textAlign?: string;
textDecoration?: string;
textShadow?: string;
textTransform?: string;
'::placeholder'?: {
color?: string;
fontWeight?: string;
};
'::selection'?: {
backgroundColor?: string;
};
':-webkit-autofill'?: {
color?: string;
};
':disabled'?: {
color?: string;
};
':focus'?: {
color?: string;
};
':hover'?: {
color?: string;
};
'@media screen and (max-width: 30em)'?: StripeElementStyleVariant;
}Install with Tessl CLI
npx tessl i tessl/npm-stripe--react-stripe-js