or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

address-elements.mdbank-elements.mdcard-elements.mdcheckout-components.mdcore-providers-hooks.mdembedded-checkout.mdindex.mdmessage-elements.mdpayment-elements.md

checkout-components.mddocs/

0

# Checkout Flow Components

1

2

Specialized components and providers for optimized checkout experiences. These components are available from the `/checkout` entry point and provide enhanced functionality for checkout-specific workflows.

3

4

## Import Path

5

6

```typescript

7

import {

8

CheckoutProvider,

9

useCheckout,

10

BillingAddressElement,

11

ShippingAddressElement,

12

CurrencySelectorElement,

13

PaymentElement,

14

ExpressCheckoutElement,

15

TaxIdElement

16

} from "@stripe/react-stripe-js/checkout";

17

```

18

19

## Capabilities

20

21

### CheckoutProvider

22

23

Specialized context provider for checkout flows that extends Elements functionality with checkout-specific state management.

24

25

```typescript { .api }

26

/**

27

* React context provider for checkout flows

28

* @param props - Checkout provider configuration props

29

* @returns JSX element wrapping child components with checkout context

30

*/

31

function CheckoutProvider(props: CheckoutProviderProps): JSX.Element;

32

33

interface CheckoutProviderProps {

34

/** Stripe instance or Promise resolving to Stripe instance */

35

stripe: PromiseLike<Stripe | null> | Stripe | null;

36

/** Checkout configuration options - REQUIRED */

37

options: StripeCheckoutOptions;

38

/** Child components that will have access to checkout context */

39

children: ReactNode;

40

}

41

```

42

43

### useCheckout Hook

44

45

React hook for accessing checkout state and functionality within checkout flows.

46

47

```typescript { .api }

48

/**

49

* Hook to access checkout state from CheckoutProvider context

50

* @returns Current checkout state

51

*/

52

function useCheckout(): CheckoutState;

53

54

type CheckoutState =

55

| {type: 'loading'}

56

| {type: 'success'; checkout: CheckoutValue}

57

| {type: 'error'; error: {message: string}};

58

59

type CheckoutValue = StripeCheckoutActions & StripeCheckoutSession;

60

61

interface StripeCheckoutActions {

62

/** Confirm the checkout payment */

63

confirm(): Promise<{error?: StripeError}>;

64

/** Cancel the checkout session */

65

cancel(): void;

66

/** Redirect to the checkout URL */

67

redirect(): void;

68

}

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

import React from 'react';

75

import { CheckoutProvider, useCheckout } from '@stripe/react-stripe-js/checkout';

76

import { loadStripe } from '@stripe/stripe-js';

77

78

const stripePromise = loadStripe('pk_test_...');

79

80

const CheckoutStatus = () => {

81

const checkoutState = useCheckout();

82

83

switch (checkoutState.type) {

84

case 'loading':

85

return <div>Loading checkout...</div>;

86

87

case 'success':

88

return (

89

<div className="checkout-success">

90

<h2>Checkout Ready</h2>

91

<button onClick={() => checkoutState.checkout.confirm()}>

92

Confirm Payment

93

</button>

94

<button onClick={() => checkoutState.checkout.cancel()}>

95

Cancel

96

</button>

97

</div>

98

);

99

100

case 'error':

101

return (

102

<div className="checkout-error">

103

<h2>Checkout Error</h2>

104

<p>{checkoutState.error.message}</p>

105

</div>

106

);

107

108

default:

109

return null;

110

}

111

};

112

113

const CheckoutFlow = ({ checkoutSessionId }) => {

114

return (

115

<CheckoutProvider stripe={stripePromise}>

116

<div className="checkout-container">

117

<h1>Complete Your Purchase</h1>

118

<CheckoutStatus />

119

</div>

120

</CheckoutProvider>

121

);

122

};

123

```

124

125

### BillingAddressElement

126

127

Specialized address element optimized for billing address collection in checkout flows.

128

129

```typescript { .api }

130

/**

131

* Billing address element for checkout flows

132

* @param props - Billing address element configuration props

133

* @returns JSX element for billing address collection

134

*/

135

function BillingAddressElement(props: BillingAddressElementProps): JSX.Element;

136

137

interface BillingAddressElementProps extends ElementProps {

138

/** Configuration options for billing address */

139

options?: StripeCheckoutAddressElementOptions;

140

/** Triggered when the Element is fully rendered */

141

onReady?: (element: StripeAddressElement) => any;

142

/** Triggered when the escape key is pressed */

143

onEscape?: () => any;

144

/** Triggered when the Element fails to load */

145

onLoadError?: (event: {elementType: 'address'; error: StripeError}) => any;

146

/** Triggered when the loader UI is mounted */

147

onLoaderStart?: (event: {elementType: 'address'}) => any;

148

}

149

150

interface StripeCheckoutAddressElementOptions {

151

/** Fields to collect */

152

fields?: {

153

phone?: 'auto' | 'always' | 'never';

154

};

155

/** Address validation options */

156

validation?: {

157

mode?: 'auto' | 'always' | 'never';

158

};

159

/** Default values */

160

defaultValues?: {

161

name?: string;

162

address?: {

163

line1?: string;

164

line2?: string;

165

city?: string;

166

state?: string;

167

postal_code?: string;

168

country?: string;

169

};

170

phone?: string;

171

};

172

}

173

```

174

175

### ShippingAddressElement

176

177

Specialized address element optimized for shipping address collection in checkout flows.

178

179

```typescript { .api }

180

/**

181

* Shipping address element for checkout flows

182

* @param props - Shipping address element configuration props

183

* @returns JSX element for shipping address collection

184

*/

185

function ShippingAddressElement(props: ShippingAddressElementProps): JSX.Element;

186

187

interface ShippingAddressElementProps extends ElementProps {

188

/** Configuration options for shipping address */

189

options?: StripeCheckoutAddressElementOptions;

190

/** Triggered when the Element is fully rendered */

191

onReady?: (element: StripeAddressElement) => any;

192

/** Triggered when the escape key is pressed */

193

onEscape?: () => any;

194

/** Triggered when the Element fails to load */

195

onLoadError?: (event: {elementType: 'address'; error: StripeError}) => any;

196

/** Triggered when the loader UI is mounted */

197

onLoaderStart?: (event: {elementType: 'address'}) => any;

198

}

199

```

200

201

**Address Elements Usage Example:**

202

203

```typescript

204

import React, { useState } from 'react';

205

import {

206

CheckoutProvider,

207

BillingAddressElement,

208

ShippingAddressElement,

209

PaymentElement

210

} from '@stripe/react-stripe-js/checkout';

211

212

const CheckoutForm = ({ stripePromise }) => {

213

const [billingAddress, setBillingAddress] = useState(null);

214

const [shippingAddress, setShippingAddress] = useState(null);

215

const [sameAsShipping, setSameAsShipping] = useState(false);

216

217

const handleBillingChange = (event) => {

218

if (event.complete) {

219

setBillingAddress(event.value);

220

}

221

};

222

223

const handleShippingChange = (event) => {

224

if (event.complete) {

225

setShippingAddress(event.value);

226

if (sameAsShipping) {

227

setBillingAddress(event.value);

228

}

229

}

230

};

231

232

return (

233

<CheckoutProvider stripe={stripePromise}>

234

<form className="checkout-form">

235

<div className="address-section">

236

<h3>Shipping Address</h3>

237

<ShippingAddressElement

238

options={{

239

fields: {

240

phone: 'always'

241

},

242

validation: {

243

mode: 'auto'

244

}

245

}}

246

onChange={handleShippingChange}

247

/>

248

</div>

249

250

<div className="billing-section">

251

<label>

252

<input

253

type="checkbox"

254

checked={sameAsShipping}

255

onChange={(e) => setSameAsShipping(e.target.checked)}

256

/>

257

Same as shipping address

258

</label>

259

260

{!sameAsShipping && (

261

<>

262

<h3>Billing Address</h3>

263

<BillingAddressElement

264

options={{

265

fields: {

266

phone: 'never'

267

}

268

}}

269

onChange={handleBillingChange}

270

/>

271

</>

272

)}

273

</div>

274

275

<div className="payment-section">

276

<h3>Payment Information</h3>

277

<PaymentElement />

278

</div>

279

280

<button

281

type="submit"

282

disabled={!billingAddress || !shippingAddress}

283

>

284

Complete Purchase

285

</button>

286

</form>

287

</CheckoutProvider>

288

);

289

};

290

```

291

292

### CurrencySelectorElement

293

294

Currency selection element for international checkout flows (requires beta access).

295

296

```typescript { .api }

297

/**

298

* Currency selector element for international checkouts

299

* Requires beta access - contact Stripe support for more information

300

* @param props - Currency selector element configuration props

301

* @returns JSX element for currency selection

302

*/

303

function CurrencySelectorElement(props: CurrencySelectorElementProps): JSX.Element;

304

305

interface CurrencySelectorElementProps extends ElementProps {

306

/** Triggered when the Element is fully rendered */

307

onReady?: (element: StripeCurrencySelectorElement) => any;

308

/** Triggered when the escape key is pressed */

309

onEscape?: () => any;

310

/** Triggered when the Element fails to load */

311

onLoadError?: (event: {elementType: 'currencySelector'; error: StripeError}) => any;

312

/** Triggered when the loader UI is mounted */

313

onLoaderStart?: (event: {elementType: 'currencySelector'}) => any;

314

}

315

```

316

317

### Checkout-Optimized PaymentElement

318

319

Specialized PaymentElement optimized for checkout flows with enhanced options.

320

321

```typescript { .api }

322

/**

323

* Payment element optimized for checkout flows

324

* @param props - Checkout payment element configuration props

325

* @returns JSX element for payment method collection

326

*/

327

function PaymentElement(props: CheckoutPaymentElementProps): JSX.Element;

328

329

type CheckoutPaymentElementProps = Omit<PaymentElementProps, 'options'> & {

330

/** Checkout-specific payment element options */

331

options?: StripeCheckoutPaymentElementOptions;

332

};

333

334

interface StripeCheckoutPaymentElementOptions extends StripePaymentElementOptions {

335

/** Enhanced layout options for checkout */

336

layout?: {

337

type?: 'tabs' | 'accordion' | 'auto';

338

defaultCollapsed?: boolean;

339

radios?: boolean;

340

spacedAccordionItems?: boolean;

341

};

342

/** Checkout-specific payment method configuration */

343

paymentMethodOrder?: string[];

344

}

345

```

346

347

### Checkout-Optimized ExpressCheckoutElement

348

349

Express checkout element optimized for checkout flows.

350

351

```typescript { .api }

352

/**

353

* Express checkout element optimized for checkout flows

354

* @param props - Checkout express checkout element configuration props

355

* @returns JSX element for express payment methods

356

*/

357

function ExpressCheckoutElement(props: CheckoutExpressCheckoutElementProps): JSX.Element;

358

359

type CheckoutExpressCheckoutElementProps = Omit<

360

ExpressCheckoutElementProps,

361

'options' | 'onClick' | 'onCancel' | 'onShippingAddressChange' | 'onShippingRateChange'

362

> & {

363

/** Checkout-specific express checkout options */

364

options?: StripeCheckoutExpressCheckoutElementOptions;

365

};

366

367

interface StripeCheckoutExpressCheckoutElementOptions {

368

/** Payment method types to enable */

369

paymentMethods?: {

370

applePay?: 'auto' | 'always' | 'never';

371

googlePay?: 'auto' | 'always' | 'never';

372

link?: 'auto' | 'always' | 'never';

373

};

374

/** Button theme customization */

375

buttonTheme?: {

376

applePay?: 'black' | 'white' | 'white-outline';

377

googlePay?: 'black' | 'white';

378

};

379

/** Layout configuration for checkout */

380

layout?: {

381

maxColumns?: number;

382

maxRows?: number;

383

};

384

}

385

```

386

387

### Checkout-Optimized TaxIdElement

388

389

Tax ID element optimized for business checkout flows.

390

391

```typescript { .api }

392

/**

393

* Tax ID element optimized for checkout flows

394

* @param props - Checkout tax ID element configuration props

395

* @returns JSX element for tax ID collection

396

*/

397

function TaxIdElement(props: CheckoutTaxIdElementProps): JSX.Element;

398

399

interface CheckoutTaxIdElementProps extends TaxIdElementProps {

400

/** Checkout-specific tax ID options */

401

options: StripeCheckoutTaxIdElementOptions;

402

}

403

404

interface StripeCheckoutTaxIdElementOptions extends StripeTaxIdElementOptions {

405

/** Required for checkout flows */

406

required?: boolean;

407

/** Checkout-specific tax ID types */

408

supportedTypes?: Array<{

409

type: string;

410

country: string;

411

required?: boolean;

412

}>;

413

}

414

```

415

416

**Complete Checkout Flow Example:**

417

418

```typescript

419

import React, { useState } from 'react';

420

import {

421

CheckoutProvider,

422

useCheckout,

423

BillingAddressElement,

424

ShippingAddressElement,

425

PaymentElement,

426

ExpressCheckoutElement,

427

CurrencySelectorElement,

428

TaxIdElement

429

} from '@stripe/react-stripe-js/checkout';

430

import { loadStripe } from '@stripe/stripe-js';

431

432

const stripePromise = loadStripe('pk_test_...');

433

434

const FullCheckoutFlow = () => {

435

const [step, setStep] = useState('shipping');

436

const [addresses, setAddresses] = useState({

437

shipping: null,

438

billing: null

439

});

440

const [businessCheckout, setBusinessCheckout] = useState(false);

441

442

const CheckoutSteps = () => {

443

const checkoutState = useCheckout();

444

445

const handleShippingComplete = (address) => {

446

setAddresses(prev => ({ ...prev, shipping: address }));

447

setStep('billing');

448

};

449

450

const handleBillingComplete = (address) => {

451

setAddresses(prev => ({ ...prev, billing: address }));

452

setStep('payment');

453

};

454

455

const handlePaymentSubmit = async () => {

456

if (checkoutState.type === 'success') {

457

try {

458

const result = await checkoutState.checkout.confirm();

459

if (result.error) {

460

console.error('Payment failed:', result.error);

461

} else {

462

setStep('complete');

463

}

464

} catch (error) {

465

console.error('Checkout error:', error);

466

}

467

}

468

};

469

470

return (

471

<div className="checkout-steps">

472

{step === 'shipping' && (

473

<div className="step">

474

<h2>Shipping Information</h2>

475

<ShippingAddressElement

476

options={{

477

fields: { phone: 'always' },

478

validation: { mode: 'auto' }

479

}}

480

onChange={(event) => {

481

if (event.complete) {

482

handleShippingComplete(event.value);

483

}

484

}}

485

/>

486

</div>

487

)}

488

489

{step === 'billing' && (

490

<div className="step">

491

<h2>Billing Information</h2>

492

493

<label>

494

<input

495

type="checkbox"

496

checked={businessCheckout}

497

onChange={(e) => setBusinessCheckout(e.target.checked)}

498

/>

499

This is a business purchase

500

</label>

501

502

<BillingAddressElement

503

options={{

504

fields: { phone: 'never' },

505

defaultValues: addresses.shipping

506

}}

507

onChange={(event) => {

508

if (event.complete) {

509

handleBillingComplete(event.value);

510

}

511

}}

512

/>

513

514

{businessCheckout && (

515

<div className="business-info">

516

<h3>Business Information</h3>

517

<TaxIdElement

518

options={{

519

required: true,

520

supportedTypes: [

521

{ type: 'us_ein', country: 'US', required: true },

522

{ type: 'eu_vat', country: 'DE' }

523

]

524

}}

525

/>

526

</div>

527

)}

528

</div>

529

)}

530

531

{step === 'payment' && (

532

<div className="step">

533

<h2>Payment Method</h2>

534

535

<div className="express-checkout">

536

<ExpressCheckoutElement

537

options={{

538

paymentMethods: {

539

applePay: 'auto',

540

googlePay: 'auto',

541

link: 'auto'

542

},

543

buttonTheme: {

544

applePay: 'black',

545

googlePay: 'black'

546

}

547

}}

548

/>

549

550

<div className="divider">or</div>

551

</div>

552

553

<PaymentElement

554

options={{

555

layout: {

556

type: 'tabs',

557

defaultCollapsed: false

558

},

559

paymentMethodOrder: ['card', 'klarna', 'afterpay_clearpay']

560

}}

561

/>

562

563

<button

564

onClick={handlePaymentSubmit}

565

disabled={checkoutState.type !== 'success'}

566

className="submit-payment"

567

>

568

Complete Purchase

569

</button>

570

</div>

571

)}

572

573

{step === 'complete' && (

574

<div className="step">

575

<h2>Order Complete!</h2>

576

<p>Thank you for your purchase.</p>

577

</div>

578

)}

579

</div>

580

);

581

};

582

583

return (

584

<CheckoutProvider stripe={stripePromise}>

585

<div className="checkout-container">

586

<div className="checkout-progress">

587

<div className={`step ${step === 'shipping' ? 'active' : ''}`}>

588

Shipping

589

</div>

590

<div className={`step ${step === 'billing' ? 'active' : ''}`}>

591

Billing

592

</div>

593

<div className={`step ${step === 'payment' ? 'active' : ''}`}>

594

Payment

595

</div>

596

</div>

597

598

<CheckoutSteps />

599

</div>

600

</CheckoutProvider>

601

);

602

};

603

604

export default FullCheckoutFlow;

605

```

606

607

## Error Handling in Checkout Flows

608

609

```typescript

610

const CheckoutWithErrorHandling = () => {

611

const [errors, setErrors] = useState({});

612

613

const handleElementError = (elementType) => (event) => {

614

if (event.error) {

615

setErrors(prev => ({

616

...prev,

617

[elementType]: event.error.message

618

}));

619

} else {

620

setErrors(prev => {

621

const newErrors = { ...prev };

622

delete newErrors[elementType];

623

return newErrors;

624

});

625

}

626

};

627

628

const hasErrors = Object.keys(errors).length > 0;

629

630

return (

631

<CheckoutProvider stripe={stripePromise}>

632

<div className="checkout-with-errors">

633

{hasErrors && (

634

<div className="error-summary">

635

<h3>Please fix the following errors:</h3>

636

<ul>

637

{Object.entries(errors).map(([element, error]) => (

638

<li key={element}>

639

<strong>{element}:</strong> {error}

640

</li>

641

))}

642

</ul>

643

</div>

644

)}

645

646

<ShippingAddressElement

647

onChange={handleElementError('shipping')}

648

onLoadError={handleElementError('shipping')}

649

/>

650

651

<BillingAddressElement

652

onChange={handleElementError('billing')}

653

onLoadError={handleElementError('billing')}

654

/>

655

656

<PaymentElement

657

onChange={handleElementError('payment')}

658

onLoadError={handleElementError('payment')}

659

/>

660

661

<button disabled={hasErrors}>

662

Complete Purchase

663

</button>

664

</div>

665

</CheckoutProvider>

666

);

667

};

668

```