# Checkout screen

> The last step before paying: delivery address and payment method pickers, delivery options, the order summary with totals that roll when the delivery changes, and slide to pay in thumb reach. Paying covers the screen with a success check and confetti, then hands over through onDone.

- Type: Component (screens)
- Access: Pro
- Page: https://goodui.dev/native/components/checkout-screen
- Markdown: https://goodui.dev/native/components/checkout-screen.md
- Registry item: https://goodui.dev/native/r/checkout-screen.json
- Dependencies: react-native-svg
- Keywords: react native checkout screen, expo payment screen, slide to pay, delivery options, order summary, address picker, payment method select, order confirmation animation

## When to use

- Confirming a shop, grocery or food order: where it goes, how it is paid, how fast it arrives.
- Any purchase where a stray tap must not pay: slide to pay asks for a deliberate gesture.

## When not to use

- Editing quantities and promo codes: do that in cart-screen first.
- Subscriptions: use paywall-screen.
- Collecting a new card number: open your payment provider's sheet from the payment step; this screen picks among saved methods.

## Installation

With the shadcn CLI (needs a components.json in the Expo app), then `npx expo install --fix` so native dependencies match your Expo SDK. The foundation comes along the first time.

```bash
npx shadcn@latest add @goodui-native-pro/checkout-screen
npx expo install --fix
```

Pro: add `"@goodui-native-pro": { "url": "https://goodui.dev/native/r/pro/{name}.json", "headers": { "Authorization": "Bearer ${GOODUI_LICENSE_KEY}" } }` to the `registries` of components.json and put your license key in .env.local.

The component lands in `components/goodui-native/checkout-screen/` and imports the foundation from `components/goodui-native/foundation/` with relative paths; it also installs banner, icon-button, list-row, locale, rolling-number, select, success-check, swipe-to-confirm.

### Setup

- Wrap the app in GestureHandlerRootView and ThemeProvider (sheets and the success check render in its overlay layer).

Built-in strings follow `<GooduiLocaleProvider>` (one [language pack](https://goodui.dev/native/r/locale-tr.json) translates the whole kit); the `labels` prop overrides them for one instance.

## Usage

```tsx
// app/checkout.tsx
import { Stack, router } from "expo-router";
import { CheckoutScreen } from "@/components/goodui-native/checkout-screen/checkout-screen";
import { api, useCart, useProfile } from "@/lib/shop";

export default function CheckoutRoute() {
  const cart = useCart();
  const { addresses, cards } = useProfile();
  return (
    <>
      <Stack.Screen options={{ headerShown: false }} />
      <CheckoutScreen
        items={cart.items}
        discount={cart.discount}
        currency="EUR"
        addresses={addresses} // [{ id, label: "Home", name, line }]
        paymentMethods={cards.map((c) => ({ id: c.id, label: `${c.brand} •••• ${c.last4}`, description: `Expires ${c.exp}` }))}
        deliveryOptions={[
          { id: "standard", label: "Standard", description: "Thu 6 to Mon 10 Nov", price: 0 },
          { id: "express", label: "Express", description: "Arrives tomorrow", price: 9.9 },
        ]}
        onPay={(order) => api.placeOrder(order)} // resolve { orderNumber, arrives } or reject new Error("Card declined")
        onDone={(receipt) => router.replace(`/orders/${receipt?.orderNumber}`)}
        onBack={() => router.back()}
      />
    </>
  );
}
```

## Examples

### On its own, with sample addresses, cards and items

```tsx
<CheckoutScreen onDone={() => router.replace("/orders")} />
```

### A payment that can be declined

```tsx
<CheckoutScreen onPay={async (order) => { const r = await api.pay(order); if (!r.ok) throw new Error("Your bank declined the payment."); return { orderNumber: r.id }; }} />
```

## API reference

### CheckoutScreen

`import { CheckoutScreen } from "@/components/goodui-native/checkout-screen/checkout-screen";`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `addresses` | `CheckoutAddress[]` | `defaultAddresses` | – |
| `paymentMethods` | `CheckoutPaymentMethod[]` | `defaultPayments` | – |
| `deliveryOptions` | `CheckoutDeliveryOption[]` | – | – |
| `items` | `CheckoutItem[]` | `defaultItems` | – |
| `discount` | `number` | `0` | Amount taken off the subtotal, for example from a promo code. |
| `currency` | `string` | `"EUR"` | ISO 4217 code for every amount. Default "EUR". |
| `defaultAddressId` | `string` | – | Starting selections. Default the first of each. |
| `defaultPaymentMethodId` | `string` | – | – |
| `defaultDeliveryOptionId` | `string` | – | – |
| `onPay` | `(order: CheckoutOrder) => Promise<CheckoutReceipt \| void>` | `() => new Promise((resolve) => setTimeout(() => resolve({ orderNumber: "PN-48213" }), 1200))` | Runs when the slider reaches the end. Return a promise that resolves with the order number; the slider shows the pending state, then the success check covers the screen. A rejection shows its message in a banner. |
| `onDone` | `(receipt: CheckoutReceipt \| null) => void` | – | After the success check, on its timer or a tap. Navigate to the order here. |
| `onBack` | `() => void` | – | Back button. Hidden when omitted. |
| `locale` | `string` | – | BCP 47 locale for amounts. Defaults to the device locale. |
| `labels` | `Partial<CheckoutScreenLabels>` | – | Overrides for the built-in strings; a GooduiLocaleProvider pack sets them app-wide. |
| `style` | `StyleProp<ViewStyle>` | – | Style for the outer container. |
| `testID` | `string` | – | Identifier for end-to-end tests. |

## Accessibility

- 'Checkout' is the header; Back is a labelled icon button.
- Address and payment are Select fields named by their labels ('Deliver to', 'Pay with') that open a sheet list with checks.
- Delivery options are checkable rows (radio behaviour); picking one announces the option and the new total.
- Slide to pay is one button: screen readers activate it with a double tap, the web with Enter or Space; the result is announced.
- A declined payment shows a danger banner with the reason, announced when it appears. The success check is announced and closes on a tap or Escape.

## Motion

- Changing the delivery option rolls the delivery fee and the total, and the slider's 'Slide to pay' amount updates.
- Slide to pay follows the finger 1:1, ticks at the point of no return, gathers into a spinner while onPay runs, then the success check springs in over the screen, draws its check and bursts confetti.
- A rejection opens the slider into 'Declined' with a shake, springs the thumb back and slides the banner down.
- Reduced motion: digits change in place, the slider's releases jump and its states crossfade, the check appears complete without ring or confetti physics, the banner fades.

## Haptics

- select when the slider crosses the point of no return; confirm or error when onPay settles (SwipeToConfirm)
- celebrate as the check lands with its confetti (SuccessCheck)
- select when a delivery row or a Select option is picked (ListRow, Select)
- error when the decline banner appears (Banner)

## Performance

- The slider and success check animate on the UI thread; Select sheets mount only while open; React renders on selection changes and payment results.

## Notes for AI

- onPay receives { addressId, paymentMethodId, deliveryOptionId, total } and must return a promise: resolve with { orderNumber, arrives? } (shown under the check), or reject with an Error whose message is shown in the banner.
- onDone runs after the success check closes (about 2.2 s, or a tap); navigate to the order there. The slider stays confirmed (resetAfter={false}).
- Without deliveryOptions the screen offers Standard (free), Express (9.90) and Pick up in store with dates from the device clock; pass your own options with a price per option (0 shows Free).
- The slider is disabled until an address, a payment method and a delivery option are selected and there is at least one item.
- Render it full-bleed with the navigator header hidden (headerShown: false); it handles the safe areas itself.

## Related

- [Cart screen](https://goodui.dev/native/components/cart-screen.md): A shopping cart: line items with a quantity stepper whose minus turns into remove, swipe left to remove or save for later, a promo code field, a free delivery meter and totals that roll with every change above a checkout bar. Removing an item offers Undo; an empty cart shows its own empty state.
- [Order tracking screen](https://goodui.dev/native/components/order-tracking-screen.md): Live order status: the arrival estimate with minutes that roll as they count down, a timeline whose line fills into each step as the order moves on (finished steps draw a check, the current one breathes), the courier with call and message buttons, and the items. Delivery lands a success check and asks for a rating.
- [Swipe to confirm](https://goodui.dev/native/components/swipe-to-confirm.md): Slide to confirm: the thumb follows the finger 1:1, the track fills behind it and the label fades, a tick marks the point of no return, and at the end the track gathers into a spinner and opens into the result.
- [Success check](https://goodui.dev/native/components/success-check.md): A success or error moment: the circle springs in, the check draws itself while a ring pulses out and the title rises in; the error variant draws a cross and shakes once. Inline or fullscreen, optionally with confetti.
- [Select](https://goodui.dev/native/components/select.md): A field that opens a bottom sheet list with search, sections and checkmarks that draw themselves in. Single mode closes on a pick; multiple mode shows the picks as chips in the field that grow in and shrink away live behind the sheet.
- [List row](https://goodui.dev/native/components/list-row.md): Settings and navigation cells with a token-colored icon tile, title, subtitle and a trailing value, switch, badge, check or chevron, grouped in inset sections with headers and footers. On touch down the highlight floods in, the tile sinks and the chevron leans forward; on release the highlight lingers and fades.

## Guidance for AI tools

Checkout screen: The last step before paying: delivery address and payment method pickers, delivery options, the order summary with totals that roll when the delivery changes, and slide to pay in thumb reach. Paying covers the screen with a success check and confetti, then hands over through onDone. Use only the documented props. Keep accessibility, reduced motion and both color schemes intact when adapting it.

Full library index: https://goodui.dev/native/llms.txt
