Skip to content
kerfjsGitHub

Checkout

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

SourcePackage @kerf-js/veneer

Preview

tsx
import { state } from '@kerf-js/core'import {  Checkout,  PayFrame,  Toaster} from '@kerf-js/veneer'import type { PlaceOrderResult } from '@kerf-js/veneer'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 === 'KERF10'            ? { 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: 'Kerf 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 @kerf-js/veneer

Usage

tsx
import { Checkout } from '@kerf-js/veneer'

Accessibility

  • This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and veneer'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.

RelatedCart drawerPay frameOrder confirmation