Skip to content
weftGitHub

Checkout

Cart, address, shipping, payment and review, as one guided flow.

SourcePackage @weft-js/warp

Preview

tsx
import { state } from '@weft-js/core'import { Checkout, PayFrame, Toaster } from '@weft-js/warp'import type { PlaceOrderResult } from '@weft-js/warp'export function Shop() {  const cart = state(SHOP_CART)  const place = async (): Promise<PlaceOrderResult> => {    await wait(900)    return { order: { id: 'T-2041', stage: 'placed' } }  }  return (    <>      <Checkout cart={cart} shipping={SHOP_SHIPPING} countries={['US', 'GB', 'DE']} taxRate={0.08} coupon={code => (code === 'WEFT10' ? { code, percentOff: 10 } : undefined)} payment={<PAYMENT_FRAME />} onPlaceOrder={place} onContinueShopping={() => (cart.value = SHOP_CART)} />      <Toaster />    </>  )}const SHOP_CART = [  { id: 'key', name: 'Security key, USB-C', variant: 'Pack of 2', price: 58, quantity: 1 },  { id: 'hoodie', name: 'weft hoodie', variant: 'Graphite · M', price: 64, quantity: 1 },  { id: 'stickers', name: 'Sticker sheet', variant: 'Deploy on Friday', price: 6, quantity: 2 },]const SHOP_SHIPPING = [{ id: 'std', name: 'Standard', eta: 'Arrives Thu 6 Nov', price: 0 }, { id: 'exp', name: 'Express', eta: 'Arrives Mon 3 Nov', price: 12 }]const wait = (ms: number) => new Promise<void>(done => { setTimeout(done, ms) })const providerFields = (el: HTMLElement) => {  const fields = el.ownerDocument.createElement('p')  fields.textContent = 'Your payment provider mounts its fields here.'  el.append(fields)  return { destroy: () => fields.remove() }}const PAYMENT_FRAME = () => <PayFrame title="Card fields from your payment provider" testMode ready mount={providerFields} />

Installation

npm install @weft-js/warp

Usage

tsx
import { Checkout } from '@weft-js/warp'

Accessibility

  • This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and warp's parts keep their roles and labels.

API Reference

PropTypeDefaultDescription
cartState<CartLine[]>—The lines, as a state, so quantity changes flow through the totals.
shippingShippingOption[]—The delivery choices.
countriesstring[]—Country codes for the address form.
defaultCountrystring'US'The country selected at the start.
addressProviderAddressProvider—Address lookup, if you have one.
taxRatenumber0A flat rate, such as 0.08.
currencystring—The ISO 4217 code prices are shown in, such as EUR.
localestring—The language and region used to format values.
paymentunknown—The payment step's body, usually a PayFrame.
wallet{ label: string; onClick: () => void; }—A saved wallet's button above the card form.
coupon((code: string) => Coupon | Promise<Coupon | undefined> | undefined)—Checks a code. Resolve undefined when it is not valid.
idempotencyKeystring—Your key for this attempt, sent again on a retry.
signInHrefstring—Shows a sign-in link at the start.
EventTypeDefaultDescription
onPlaceOrder(order: OrderDraft) => Promise<PlaceOrderResult>—Places the order. Return the order, or a typed error that sends people to the right step.
onStepChange((step: CheckoutStep) => void)—Called on every step change.
onContinueShopping(() => void)—The button on the final step.

Parts

Every element carries a stable name, so you can style it from your own CSS: [data-scope="checkout"] [data-part="trigger"]

triggerstep-titlenavlayoutstepstep-bodycolssr-onlyradiodividersummarythumbpricetotal

RelatedCart drawerPay frameOrder confirmation