Checkout Page Flow
The checkout page flow is built from TestCheckoutDemo. It combines form-controlled checkout primitives with a read-only order summary that reuses cart item and total atoms.
Flow Structure
CheckoutProvider
CheckoutForm
BillingAddressForm
ShippingAddressForm
ShippingMethodSelector
PaymentMethodSelector
TermsCheckbox
CheckoutNotices
PlaceOrderButton
OrderSummary
Product row slot
CartItemTitle
CartAttributeList
CartItemSubtotal
Totals slot
OrderSummaryTotalsList
TotalsSubtotal
TotalsDiscount
TotalsShipping
TotalsTax
TotalsTotal
CheckoutProvider scopes checkout state for the form and child controls. CheckoutForm owns the submit event and the final Store API checkout request.
Address Forms
BillingAddressForm and ShippingAddressForm share address form props and markup generation. They render fields from the checkout field schema, not from hard-coded field lists in the docs.
The checkout runtime handles:
- required billing fields,
- email validation,
- country and state selectors,
- state field visibility when the selected country has no state options,
- the shipping-address toggle and its embedded field group,
- local blocking before Store API submit when known-invalid fields are present.
E2E verifies country/state refresh and local validation behavior before checkout requests are sent.
Selectors
ShippingMethodSelector and PaymentMethodSelector use the shared UIChoice mode logic. Both support select and button-radio presentation. In checkout, selected values are written into checkout state before the form is submitted.
Shipping method options come from package-aware Store API rates. Payment options come from Store API payment methods. The demo checkout uses select mode for both.
Terms, Notices, And Submit
TermsCheckbox blocks submit when it is required and unchecked. CheckoutNotices renders checkout-scoped error messages. PlaceOrderButton triggers the parent CheckoutForm.
The form sets data-ome-state during validation, pending submit, success, and error states so authors can style the visible state without replacing the native Woo order lifecycle.
Order Summary
OrderSummary is read-only. It renders current cart products and totals inside checkout, but it does not submit or mutate checkout data. The demo uses the full_atoms mode so product rows and totals are authored through slots:
| Slot | Components used |
|---|---|
products | CartItemTitle, CartAttributeList, CartItemSubtotal. |
totals | OrderSummaryTotalsList with subtotal, discount, shipping, tax, and total atoms. |
This reuse keeps cart and checkout total display aligned with the same normalized cart data.
Store API And Native Hooks
Checkout submission goes through Woo Store API checkout. Lifecycle E2E verifies native Woo hooks still run through this path, including woocommerce_store_api_checkout_update_order_from_request and woocommerce_rest_checkout_process_payment_with_context.
That means Etch components can be authored visually while Woo plugins that rely on native checkout hooks still see the checkout lifecycle.
E2E Coverage
| Scenario | Verified behavior |
|---|---|
checkout_success | A full checkout form submits a real order. |
checkout_validation_error | Invalid required fields are marked locally. |
checkout_terms_blocked | Required terms block checkout and render notices. |
checkout_terms_success | Checked terms allow the normal success flow. |
payment_selector_button_radio | Payment selector button-radio mode renders and selects values. |
payment_selector_select | Payment selector select mode renders trigger/content and selected values. |
shipping_selector_select | Checkout-compatible shipping selection works in select mode. |
lifecycle_checkout | Store API checkout completes through native Woo lifecycle hooks. |