Checkout
The checkout system is a multi-step flow: Contact → Delivery → Payment → Confirmation. All option values (delivery methods, countries, cities, payment methods) are fetched from store settings automatically — no options props needed.
Multi-Step Checkout
<CheckoutSettingsProvider>
<CheckoutProvider>
<CheckoutContactStep>
<div class="space-y-4">
<CheckoutEmailTextField />
<CheckoutNameTextField />
<CheckoutPhoneTextField />
<CheckoutNotesTextArea />
</div>
</CheckoutContactStep>
<CheckoutDeliveryStep>
<div class="space-y-4">
<CheckoutDeliveryMethodSegmentedControl>
<SegmentedControlItems>
<SegmentedControlItem>
<SegmentedControlItemLabel />
</SegmentedControlItem>
</SegmentedControlItems>
</CheckoutDeliveryMethodSegmentedControl>
<CheckoutCountrySelect>
<SelectTrigger>
<SelectValue placeholder="Select country" />
</SelectTrigger>
<SelectContent>
<SelectListbox />
</SelectContent>
</CheckoutCountrySelect>
<CheckoutDeliveryCitySelect>
<SelectTrigger>
<SelectValue placeholder="Select city" />
</SelectTrigger>
<SelectContent>
<SelectListbox />
</SelectContent>
</CheckoutDeliveryCitySelect>
<CheckoutDeliveryZoneMethod>
<CheckoutDeliveryZoneMethodLabel class="font-semibold" />
<CheckoutDeliveryZoneMethodPrice />
</CheckoutDeliveryZoneMethod>
</div>
</CheckoutDeliveryStep>
<CheckoutPaymentStep>
<div class="space-y-4">
<CheckoutPaymentMethodRadioGroup>
<CheckoutPaymentMethod method="mpesa">
<RadioGroupItem value="mpesa">
<RadioGroupItemLabel>M-Pesa</RadioGroupItemLabel>
<RadioGroupItemDescription>Pay via mobile money</RadioGroupItemDescription>
</RadioGroupItem>
</CheckoutPaymentMethod>
<CheckoutPaymentMethod method="stripe">
<RadioGroupItem value="stripe">
<RadioGroupItemLabel>Card</RadioGroupItemLabel>
<RadioGroupItemDescription>Debit or credit card</RadioGroupItemDescription>
</RadioGroupItem>
</CheckoutPaymentMethod>
</CheckoutPaymentMethodRadioGroup>
<CheckoutPaymentPhoneTextField />
<CheckoutSubmitProvider>
<CheckoutButton>Place Order</CheckoutButton>
<CheckoutLoading />
<CheckoutErrorMessage />
</CheckoutSubmitProvider>
</div>
</CheckoutPaymentStep>
</CheckoutProvider>
</CheckoutSettingsProvider>
Payment Methods with Accordion
Each payment method expands to reveal its fields (M-Pesa shows a phone input, Stripe shows card details). The accordion trigger doubles as the selection control:
<Accordion>
<CheckoutPaymentMethod method="mpesa">
<AccordionItem value="mpesa">
<AccordionTrigger>
<CheckoutPaymentMethodSelectButton>
<span>M-Pesa</span>
<span class="text-xs text-muted-foreground">Pay via mobile money</span>
</CheckoutPaymentMethodSelectButton>
</AccordionTrigger>
<AccordionContent>
<div class="space-y-4 pt-4">
<CheckoutPaymentPhoneTextField />
</div>
</AccordionContent>
</AccordionItem>
</CheckoutPaymentMethod>
<CheckoutPaymentMethod method="stripe">
<AccordionItem value="stripe">
<AccordionTrigger>
<CheckoutPaymentMethodSelectButton>
<span>Card</span>
<span class="text-xs text-muted-foreground">Debit or credit card</span>
</CheckoutPaymentMethodSelectButton>
</AccordionTrigger>
<AccordionContent>
<div class="space-y-4 pt-4">
<p class="text-sm text-muted-foreground">Card details handled securely by Stripe</p>
</div>
</AccordionContent>
</AccordionItem>
</CheckoutPaymentMethod>
</Accordion>
<CheckoutSubmitProvider>
<CheckoutButton>Place Order</CheckoutButton>
</CheckoutSubmitProvider>
CheckoutPaymentMethod gates each accordion item by store settings — if a payment method isn't enabled, its section is hidden. CheckoutPaymentMethodSelectButton writes to formData.paymentMethod and sets data-selected when active.
Delivery Method Selection
Three variants — use whichever fits your design:
{/* Dropdown */}
<CheckoutDeliveryMethodSelect>
<SelectTrigger><SelectValue /></SelectTrigger>
<SelectContent><SelectListbox /></SelectContent>
</CheckoutDeliveryMethodSelect>
{/* Radio group */}
<CheckoutDeliveryMethodRadioGroup>
<RadioGroupItems>
<RadioGroupItem>
<RadioGroupItemLabel />
</RadioGroupItem>
</RadioGroupItems>
</CheckoutDeliveryMethodRadioGroup>
{/* Segmented control (pills) */}
<CheckoutDeliveryMethodSegmentedControl>
<SegmentedControlItems>
<SegmentedControlItem>
<SegmentedControlItemLabel />
</SegmentedControlItem>
</SegmentedControlItems>
</CheckoutDeliveryMethodSegmentedControl>
Options are auto-fetched from delivery zones. No options prop needed.
Country & City Selection
Countries and cities are also auto-derived from delivery zones. Same three-variant pattern:
{/* Country */}
<CheckoutCountrySelect>
<SelectTrigger><SelectValue placeholder="Country" /></SelectTrigger>
<SelectContent><SelectListbox /></SelectContent>
</CheckoutCountrySelect>
{/* City — filtered by selected country */}
<CheckoutDeliveryCitySelect>
<SelectTrigger><SelectValue placeholder="City" /></SelectTrigger>
<SelectContent><SelectListbox /></SelectContent>
</CheckoutDeliveryCitySelect>
When a country is selected, the matching delivery zone auto-resolves and cities filter to that zone.
Delivery Zone
Once a country and delivery method are selected, show the resolved zone details:
<CheckoutDeliveryZoneName class="text-lg font-semibold" />
<CheckoutDeliveryZoneMethod>
<div class="flex justify-between">
<CheckoutDeliveryZoneMethodLabel />
<CheckoutDeliveryZoneMethodPrice class="font-semibold" />
</div>
<p class="text-sm text-muted-foreground">
<CheckoutDeliveryZoneMethodMinDays />
<span>–</span>
<CheckoutDeliveryZoneMethodMaxDays /> days
</p>
<CheckoutDeliveryZoneMethodConditions>
<div class="flex justify-between">
<CheckoutDeliveryZoneMethodConditionLabel />
<CheckoutDeliveryZoneMethodConditionValue />
</div>
</CheckoutDeliveryZoneMethodConditions>
<CheckoutDeliveryZoneMethodClassPrices>
<div class="flex justify-between">
<CheckoutDeliveryZoneMethodClassPriceLabel />
<CheckoutDeliveryZoneMethodClassPriceValue />
</div>
</CheckoutDeliveryZoneMethodClassPrices>
</CheckoutDeliveryZoneMethod>
Custom Field Rendering
Contact fields are self-contained with default labels and validation. Override their rendering by passing children:
<CheckoutEmailTextField>
<TextField class="flex flex-col gap-1">
<TextFieldLabel class="font-semibold">Email Address</TextFieldLabel>
<TextFieldInput class="border-2 p-3 rounded-lg" />
<TextFieldErrorMessage class="text-red-500 text-sm" />
</TextField>
</CheckoutEmailTextField>
The context binding (value, validation, onChange) is preserved — only the markup changes.
Address Fields
Shipping and billing address fields are available as standalone components:
<CheckoutShippingStreetField />
<CheckoutShippingCityField />
<CheckoutShippingStateField />
<CheckoutShippingZipField />
<CheckoutShippingCountryField />
<CheckoutBillingStreetField />
<CheckoutBillingCityField />
<CheckoutBillingStateField />
<CheckoutBillingZipField />
<CheckoutBillingCountryField />
Checkout Result
Show success or error state from the mutation:
<CheckoutResult />
Renders different content based on mutation success or error. Wrap in your own layout for custom styling.