> ## Documentation Index
> Fetch the complete documentation index at: https://primer.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Components

> Overview of all Primer Checkout components and their relationships.

export const IOS_CHECKOUT_HIERARCHY = {
  name: 'PrimerCheckout',
  type: 'root',
  badge: 'SwiftUI View',
  children: [{
    name: 'PrimerCheckoutScope',
    type: 'layout',
    badge: 'scope closure',
    children: [{
      name: 'splashScreen, loadingScreen, errorScreen',
      type: 'utility',
      note: 'customizable screens',
      inline: true
    }, {
      name: 'PrimerPaymentMethodSelectionScope',
      type: 'container',
      note: 'paymentMethodSelection',
      inline: true
    }, {
      name: 'PrimerCardFormScope',
      type: 'form',
      badge: 'card payment form',
      fullWidth: [{
        name: 'PrimerCardNumberField',
        type: 'input'
      }],
      grid: [{
        name: 'PrimerExpiryDateField',
        type: 'input'
      }, {
        name: 'PrimerCvvField',
        type: 'input'
      }],
      bottomFullWidth: [{
        name: 'PrimerCardholderNameField',
        type: 'input'
      }, {
        name: 'submitButton',
        type: 'action'
      }],
      children: [{
        name: 'PrimerSelectCountryScope',
        type: 'utility',
        note: 'selectCountry',
        inline: true
      }]
    }, {
      name: 'PrimerApplePayScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerPayPalScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerKlarnaScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerAchScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerWebRedirectScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerFormRedirectScope',
      type: 'container',
      inline: true
    }, {
      name: 'PrimerQRCodeScope',
      type: 'container',
      inline: true
    }]
  }]
};

export const ANDROID_CHECKOUT_HIERARCHY_HOST = {
  name: 'rememberPrimerCheckoutController()',
  type: 'root',
  badge: 'controller',
  children: [{
    name: 'PrimerCheckoutHost',
    type: 'layout',
    badge: 'inline host',
    children: [{
      name: 'Your layout with SDK components',
      type: 'container',
      note: 'composable lambda',
      children: [{
        name: 'PrimerPaymentMethods',
        type: 'container',
        inline: true
      }, {
        name: 'PrimerCardForm',
        type: 'form',
        inline: true
      }, {
        name: 'PrimerVaultedPaymentMethods',
        type: 'utility',
        inline: true
      }]
    }]
  }]
};

export const ANDROID_CHECKOUT_HIERARCHY_SHEET = {
  name: 'rememberPrimerCheckoutController()',
  type: 'root',
  badge: 'controller',
  children: [{
    name: 'PrimerCheckoutSheet',
    type: 'layout',
    badge: 'modal bottom sheet',
    children: [{
      name: 'PrimerCheckoutSheetDefaults.Splash',
      type: 'utility',
      inline: true
    }, {
      name: 'PrimerCheckoutSheetDefaults.Loading',
      type: 'utility',
      inline: true
    }, {
      name: 'PrimerCheckoutSheetDefaults.PaymentMethodSelection',
      type: 'container',
      children: [{
        name: 'PrimerVaultedPaymentMethods',
        type: 'utility',
        note: 'saved methods',
        inline: true
      }, {
        name: 'PrimerPaymentMethods',
        type: 'container',
        note: 'available methods',
        inline: true
      }]
    }, {
      name: 'PrimerCardForm',
      type: 'form',
      badge: 'card payment form',
      fullWidth: [{
        name: 'CardNumberField',
        type: 'input'
      }],
      grid: [{
        name: 'ExpiryField',
        type: 'input'
      }, {
        name: 'CvvField',
        type: 'input'
      }],
      bottomFullWidth: [{
        name: 'CardholderField',
        type: 'input'
      }, {
        name: 'SubmitButton',
        type: 'action'
      }]
    }, {
      name: 'PrimerCheckoutSheetDefaults.Success',
      type: 'utility',
      inline: true
    }, {
      name: 'PrimerCheckoutSheetDefaults.Error',
      type: 'error',
      inline: true
    }]
  }]
};

export const CHECKOUT_HIERARCHY_WITH_VAULT = {
  name: '<primer-checkout>',
  type: 'root',
  badge: 'root',
  children: [{
    name: '<primer-main>',
    type: 'layout',
    badge: 'slot: main',
    children: [{
      name: '<primer-vault-manager>',
      type: 'utility',
      inline: true
    }, {
      name: '<primer-show-other-payments>',
      type: 'container',
      children: [{
        name: '<primer-payment-method>',
        type: 'container',
        note: '× N',
        inline: true
      }, {
        name: '<primer-card-form>',
        type: 'form',
        badge: 'slot: card-form-content',
        fullWidth: [{
          name: 'primer-input-card-number',
          type: 'input'
        }],
        grid: [{
          name: 'primer-input-card-expiry',
          type: 'input'
        }, {
          name: 'primer-input-cvv',
          type: 'input'
        }],
        bottomFullWidth: [{
          name: 'primer-input-cardholder-name',
          type: 'input'
        }, {
          name: 'primer-card-form-submit',
          type: 'action'
        }]
      }]
    }, {
      name: '<primer-error-message-container>',
      type: 'error',
      inline: true
    }]
  }]
};

export const CHECKOUT_HIERARCHY_WITHOUT_VAULT = {
  name: '<primer-checkout>',
  type: 'root',
  badge: 'root',
  children: [{
    name: '<primer-main>',
    type: 'layout',
    badge: 'slot: main',
    children: [{
      name: '<primer-payment-method>',
      type: 'container',
      note: '× N',
      inline: true
    }, {
      name: '<primer-card-form>',
      type: 'form',
      badge: 'slot: card-form-content',
      fullWidth: [{
        name: 'primer-input-card-number',
        type: 'input'
      }],
      grid: [{
        name: 'primer-input-card-expiry',
        type: 'input'
      }, {
        name: 'primer-input-cvv',
        type: 'input'
      }],
      bottomFullWidth: [{
        name: 'primer-input-cardholder-name',
        type: 'input'
      }, {
        name: 'primer-card-form-submit',
        type: 'action'
      }]
    }, {
      name: '<primer-error-message-container>',
      type: 'error',
      inline: true
    }]
  }]
};

export const ComponentHierarchyBox = ({data}) => {
  const colors = {
    root: {
      border: '#3b82f6',
      text: '#3b82f6'
    },
    layout: {
      border: '#8b5cf6',
      text: '#8b5cf6'
    },
    container: {
      border: '#6b7280',
      text: '#6b7280'
    },
    form: {
      border: '#10b981',
      text: '#10b981'
    },
    input: {
      border: '#f59e0b',
      text: '#f59e0b'
    },
    action: {
      border: '#ef4444',
      text: '#ef4444'
    },
    error: {
      border: '#ef4444',
      text: '#ef4444'
    },
    utility: {
      border: '#6b7280',
      text: '#6b7280'
    }
  };
  const renderNode = (node, depth = 0) => {
    const color = colors[node.type] || colors.container;
    const isLeaf = !node.children || node.children.length === 0;
    const borderStyle = node.conditional ? 'dashed' : 'solid';
    return <div key={node.name} style={{
      border: '1px ' + borderStyle + ' ' + color.border,
      borderRadius: '8px',
      padding: isLeaf ? '10px 14px' : '16px',
      marginTop: depth > 0 ? '12px' : '0'
    }}>
        <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: '12px',
      marginBottom: node.children ? '12px' : '0',
      flexWrap: 'wrap'
    }}>
          <span style={{
      fontFamily: 'var(--font-mono, monospace)',
      fontSize: '14px',
      fontWeight: '500',
      color: color.text
    }}>
            {node.name}
          </span>
          {node.badge && <span style={{
      padding: '2px 8px',
      fontSize: '11px',
      fontWeight: '500',
      color: 'var(--tw-prose-body, #6b7280)',
      border: '1px solid var(--tw-prose-hr, #e5e7eb)',
      borderRadius: '4px'
    }}>
              {node.badge}
            </span>}
          {node.note && <span style={{
      fontSize: '12px',
      color: 'var(--tw-prose-body, #9ca3af)'
    }}>
              {node.note}
            </span>}
        </div>

        {node.children && <div style={{
      display: 'flex',
      flexDirection: 'column',
      gap: '0'
    }}>
            {node.children.map(child => {
      if (child.inline) {
        const childBorderStyle = child.conditional ? 'dashed' : 'solid';
        return <div key={child.name} style={{
          display: 'flex',
          alignItems: 'center',
          gap: '8px',
          padding: '8px 12px',
          border: '1px ' + childBorderStyle + ' ' + (colors[child.type] || colors.container).border,
          borderRadius: '6px',
          marginTop: '8px'
        }}>
                    <span style={{
          fontFamily: 'var(--font-mono, monospace)',
          fontSize: '13px',
          color: (colors[child.type] || colors.container).text
        }}>
                      {child.name}
                    </span>
                    {child.note && <span style={{
          fontSize: '12px',
          color: 'var(--tw-prose-body, #9ca3af)'
        }}>
                        {child.note}
                      </span>}
                  </div>;
      }
      return renderNode(child, depth + 1);
    })}
          </div>}

        {node.fullWidth && <div style={{
      marginTop: '8px'
    }}>
            {node.fullWidth.map(item => <div key={item.name} style={{
      padding: '8px 12px',
      border: '1px solid ' + (colors[item.type] || colors.input).border,
      borderRadius: '6px',
      marginTop: '8px'
    }}>
                <span style={{
      fontFamily: 'var(--font-mono, monospace)',
      fontSize: '13px',
      color: (colors[item.type] || colors.input).text
    }}>
                  {item.name}
                </span>
              </div>)}
          </div>}

        {node.grid && <div style={{
      display: 'grid',
      gridTemplateColumns: 'repeat(2, 1fr)',
      gap: '8px',
      marginTop: '8px'
    }}>
            {node.grid.map(item => <div key={item.name} style={{
      padding: '8px 12px',
      border: '1px solid ' + (colors[item.type] || colors.input).border,
      borderRadius: '6px'
    }}>
                <span style={{
      fontFamily: 'var(--font-mono, monospace)',
      fontSize: '13px',
      color: (colors[item.type] || colors.input).text
    }}>
                  {item.name}
                </span>
              </div>)}
          </div>}

        {node.bottomFullWidth && <div style={{
      marginTop: '8px'
    }}>
            {node.bottomFullWidth.map(item => <div key={item.name} style={{
      padding: '8px 12px',
      border: '1px solid ' + (colors[item.type] || colors.action).border,
      borderRadius: '6px',
      marginTop: '8px'
    }}>
                <span style={{
      fontFamily: 'var(--font-mono, monospace)',
      fontSize: '13px',
      color: (colors[item.type] || colors.action).text
    }}>
                  {item.name}
                </span>
              </div>)}
          </div>}

        {node.bottomGrid && <div style={{
      display: 'grid',
      gridTemplateColumns: 'repeat(2, 1fr)',
      gap: '8px',
      marginTop: '12px'
    }}>
            {node.bottomGrid.map(item => <div key={item.name} style={{
      padding: '10px 14px',
      border: '1px solid ' + (colors[item.type] || colors.utility).border,
      borderRadius: '6px'
    }}>
                <span style={{
      fontFamily: 'var(--font-mono, monospace)',
      fontSize: '13px',
      color: (colors[item.type] || colors.utility).text
    }}>
                  {item.name}
                </span>
              </div>)}
          </div>}
      </div>;
  };
  return <div style={{
    padding: '20px',
    borderRadius: '8px',
    border: '1px solid var(--tw-prose-hr, #e5e7eb)'
  }}>
      {renderNode(data)}
    </div>;
};

Primer Checkout provides a set of components that work together to create a complete payment experience. This page gives you an overview of all available components and how they relate to each other.

## Component Hierarchy

<Tabs>
  <Tab title="Web">
    The components follow a hierarchical structure where parent components provide context to their children. Each parent literally contains its children. The spatial nesting mirrors the DOM nesting.

    <Tabs>
      <Tab title="Without vault">
        <ComponentHierarchyBox data={CHECKOUT_HIERARCHY_WITHOUT_VAULT} />
      </Tab>

      <Tab title="With vault">
        <ComponentHierarchyBox data={CHECKOUT_HIERARCHY_WITH_VAULT} />
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="Android">
    The components follow a hierarchical structure where the checkout controller manages presentation components, which in turn contain SDK UI elements.

    <Tabs>
      <Tab title="CheckoutSheet">
        <ComponentHierarchyBox data={ANDROID_CHECKOUT_HIERARCHY_SHEET} />
      </Tab>

      <Tab title="CheckoutHost">
        <ComponentHierarchyBox data={ANDROID_CHECKOUT_HIERARCHY_HOST} />
      </Tab>
    </Tabs>
  </Tab>

  <Tab title="iOS">
    The iOS SDK uses a scope-based hierarchy where `PrimerCheckout` provides a `PrimerCheckoutScope`, which gives access to payment method-specific scopes.

    <ComponentHierarchyBox data={IOS_CHECKOUT_HIERARCHY} />
  </Tab>
</Tabs>

## Core Components

<Tabs>
  <Tab title="Web">
    | Component                                                                                                  | Purpose                                                               |
    | ---------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
    | [`<primer-checkout>`](/sdk/primer-checkout-web/components/primer-checkout)                                 | Root component that initializes the SDK and provides checkout context |
    | [`<primer-main>`](/sdk/primer-checkout-web/components/primer-main)                                         | Manages checkout states and provides layout customization             |
    | [`<primer-payment-method>`](/sdk/primer-checkout-web/components/primer-payment-method)                     | Renders a specific payment method (card, PayPal, Apple Pay, etc.)     |
    | [`<primer-payment-method-container>`](/sdk/primer-checkout-web/components/primer-payment-method-container) | Container for filtering and organizing multiple payment methods       |
  </Tab>

  <Tab title="Android">
    ### Checkout controllers

    | Function                                    | Returns                                 | Purpose                     |
    | ------------------------------------------- | --------------------------------------- | --------------------------- |
    | `rememberPrimerCheckoutController()`        | `PrimerCheckoutController`              | Main session controller     |
    | `rememberCardFormController()`              | `PrimerCardFormController`              | Card form state and actions |
    | `rememberPaymentMethodsController()`        | `PrimerPaymentMethodsController`        | Available payment methods   |
    | `rememberVaultedPaymentMethodsController()` | `PrimerVaultedPaymentMethodsController` | Saved payment methods       |

    ### Presentation components

    | Component              | Description                 | API Reference                                                                             |
    | ---------------------- | --------------------------- | ----------------------------------------------------------------------------------------- |
    | `PrimerCheckoutSheet`  | Modal bottom sheet checkout | [Reference](/sdk/android-checkout/v3.0.0-beta/api/primer-checkout-sheet)                  |
    | `PrimerCheckoutHost`   | Inline checkout host        | [Reference](/sdk/android-checkout/v3.0.0-beta/api/primer-checkout-host)                   |
    | `PrimerCardForm`       | Card payment form           | [Reference](/sdk/android-checkout/v3.0.0-beta/api/card-form/primer-card-form)             |
    | `PrimerPaymentMethods` | Payment method list         | [Reference](/sdk/android-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) |
  </Tab>

  <Tab title="iOS">
    ### Entry points

    | Component                 | Description                    | API Reference                                                                                         |
    | ------------------------- | ------------------------------ | ----------------------------------------------------------------------------------------------------- |
    | `PrimerCheckout`          | Root SwiftUI view for checkout | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-checkout)                              |
    | `PrimerCheckoutPresenter` | UIKit presenter (modal sheet)  | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/common-objects#primercheckoutpresenter-uikit) |

    ### Scopes

    | Scope                               | Purpose                                      | API Reference                                                                                  |
    | ----------------------------------- | -------------------------------------------- | ---------------------------------------------------------------------------------------------- |
    | `PrimerCheckoutScope`               | Top-level checkout management                | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-checkout-scope)                 |
    | `PrimerPaymentMethodSelectionScope` | Payment method list and selection            | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-payment-method-selection-scope) |
    | `PrimerCardFormScope`               | Card form fields and validation              | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-card-form-scope)                |
    | `PrimerApplePayScope`               | Apple Pay flow                               | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-apple-pay-scope)                |
    | `PrimerPayPalScope`                 | PayPal flow                                  | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-paypal-scope)                   |
    | `PrimerKlarnaScope`                 | Klarna multi-step flow                       | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-klarna-scope)                   |
    | `PrimerAchScope`                    | ACH multi-step flow                          | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-ach-scope)                      |
    | `PrimerWebRedirectScope`            | Web redirect flow (e.g., Twint)              | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-web-redirect-scope)             |
    | `PrimerFormRedirectScope`           | Form-based redirect flow (e.g., BLIK, MBWay) | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-form-redirect-scope)            |
    | `PrimerQRCodeScope`                 | QR code flow (e.g., PromptPay)               | [Reference](/sdk/ios-checkout/v3.0.0-beta/api-reference/primer-qr-code-scope)                  |
  </Tab>
</Tabs>

## Card Form Components

<Tabs>
  <Tab title="Web">
    | Component                                                                                                              | Purpose                                         |
    | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
    | [`<primer-card-form>`](/sdk/primer-checkout-web/components/primer-card-form/primer-card-form)                          | Container that provides context for card inputs |
    | [`<primer-input-card-number>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-number)          | Secure hosted input for card number             |
    | [`<primer-input-card-expiry>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-expiry)          | Secure hosted input for expiry date             |
    | [`<primer-input-cvv>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-cvv)                          | Secure hosted input for CVV                     |
    | [`<primer-input-cardholder-name>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-card-holder-name) | Input for cardholder name                       |
    | [`<primer-card-form-submit>`](/sdk/primer-checkout-web/components/primer-card-form/primer-card-form-submit)            | Submit button with built-in loading states      |
    | [`<primer-input-label>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-label)                      | Label component for card inputs                 |
    | [`<primer-input-wrapper>`](/sdk/primer-checkout-web/components/primer-card-form/primer-input-wrapper)                  | Wrapper for styling and layout of inputs        |
    | [`<primer-billing-address>`](/sdk/primer-checkout-web/components/primer-card-form/primer-billing-address)              | Billing address collection form                 |
  </Tab>

  <Tab title="Android">
    ### Defaults objects

    | Object                        | Parent Component       | Sub-components                                                                                                                          |
    | ----------------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
    | `PrimerCheckoutSheetDefaults` | `PrimerCheckoutSheet`  | `Splash`, `Loading`, `Success`, `Error`, `PaymentMethodSelection`, `VaultedMethods`, `PaymentMethods`                                   |
    | `CardFormDefaults`            | `PrimerCardForm`       | `CardNumberField`, `ExpiryField`, `CvvField`, `CardholderField`, `CardNetworkField`, `CountryCodeField`, billing fields, `SubmitButton` |
    | `PaymentMethodsDefaults`      | `PrimerPaymentMethods` | `SectionHeader`, `Method`, `EmptyState`                                                                                                 |

    ### State types

    | Type                             | Purpose            | Values                            |
    | -------------------------------- | ------------------ | --------------------------------- |
    | `PrimerCheckoutState`            | Checkout lifecycle | `Loading`, `Ready`                |
    | `PrimerCheckoutEvent`            | Payment outcomes   | `Success`, `Failure`              |
    | `PrimerCardFormController.State` | Card form state    | Field values, validation, loading |
  </Tab>

  <Tab title="iOS">
    ### SDK-managed fields

    `PrimerCardFormScope` provides ViewBuilder methods that return SDK-managed card fields:

    | Method                      | Purpose                                         |
    | --------------------------- | ----------------------------------------------- |
    | `PrimerCardNumberField`     | Secure card number input with network detection |
    | `PrimerExpiryDateField`     | Expiry date input                               |
    | `PrimerCvvField`            | CVV/CVC input                                   |
    | `PrimerCardholderNameField` | Cardholder name input                           |
    | `PrimerPostalCodeField`     | Postal/ZIP code input                           |
    | `PrimerCountryField`        | Country selector                                |
    | `DefaultCardFormView`       | Complete default card form layout               |

    ### State types

    | Type                                | Purpose             | Key properties                                                  |
    | ----------------------------------- | ------------------- | --------------------------------------------------------------- |
    | `PrimerCheckoutState`               | Checkout lifecycle  | `.initializing`, `.ready`, `.success`, `.failure`, `.dismissed` |
    | `PrimerCardFormState`               | Card form state     | `isValid`, `isLoading`, `fieldErrors`, `selectedNetwork`        |
    | `PrimerPaymentMethodSelectionState` | Payment method list | Available payment methods                                       |

    ### Field configuration

    Each card form field can be configured via `InputFieldConfig`:

    ```swift theme={"dark"}
    cardScope.cardNumberConfig = InputFieldConfig(
      label: "Card Number",
      placeholder: "1234 5678 9012 3456",
      styling: PrimerFieldStyling(cornerRadius: 8)
    )
    ```
  </Tab>
</Tabs>

## Utility Components

<Tabs>
  <Tab title="Web">
    | Component                                                                                                | Purpose                                          |
    | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------ |
    | [`<primer-error-message-container>`](/sdk/primer-checkout-web/components/primer-error-message-container) | Displays payment error messages                  |
    | [`<primer-vault-manager>`](/sdk/primer-checkout-web/components/primer-vault-manager)                     | Manages saved payment methods                    |
    | [`<primer-show-other-payments>`](/sdk/primer-checkout-web/components/primer-show-other-payments)         | Toggle button to show additional payment methods |
  </Tab>

  <Tab title="Android">
    ### Theming

    | Class               | Purpose              |
    | ------------------- | -------------------- |
    | `PrimerTheme`       | Root theme container |
    | `LightColorTokens`  | Light mode colors    |
    | `DarkColorTokens`   | Dark mode colors     |
    | `SpacingTokens`     | Spacing values       |
    | `TypographyTokens`  | Font styles          |
    | `RadiusTokens`      | Corner radius        |
    | `BorderWidthTokens` | Border widths        |
    | `SizeTokens`        | Component sizes      |
  </Tab>

  <Tab title="iOS">
    ### Theming

    | Struct                 | Purpose                              |
    | ---------------------- | ------------------------------------ |
    | `PrimerCheckoutTheme`  | Root theme container                 |
    | `ColorOverrides`       | Brand, text, border, and icon colors |
    | `RadiusOverrides`      | Corner radius values                 |
    | `SpacingOverrides`     | Spacing values                       |
    | `SizeOverrides`        | Component sizes                      |
    | `TypographyOverrides`  | Font styles and sizes                |
    | `BorderWidthOverrides` | Border widths                        |

    ### Type aliases

    | Alias                        | Signature                                | Used for                                        |
    | ---------------------------- | ---------------------------------------- | ----------------------------------------------- |
    | `Component`                  | `() -> any View`                         | `splashScreen`, `loadingScreen`, `submitButton` |
    | `ContainerComponent`         | `(@escaping () -> any View) -> any View` | `container`                                     |
    | `ErrorComponent`             | `(String) -> any View`                   | `errorScreen`                                   |
    | `PaymentMethodItemComponent` | `(CheckoutPaymentMethod) -> any View`    | `paymentMethodItem`                             |
    | `CardFormScreenComponent`    | `(any PrimerCardFormScope) -> any View`  | Card form `screen`                              |
  </Tab>
</Tabs>

## Basic Usage

<Tabs>
  <Tab title="Web">
    ```html theme={"dark"}
    <primer-checkout client-token="your-client-token">
      <primer-main slot="main">
        <div slot="payments">
          <!-- Payment methods appear here -->
          <primer-payment-method type="PAYMENT_CARD"></primer-payment-method>
          <primer-payment-method type="PAYPAL"></primer-payment-method>

          <!-- Error display -->
          <primer-error-message-container></primer-error-message-container>
        </div>

        <div slot="checkout-complete">
          <h2>Payment successful!</h2>
        </div>
      </primer-main>
    </primer-checkout>
    ```
  </Tab>

  <Tab title="Android">
    ```kotlin theme={"dark"}
    @Composable
    fun CheckoutScreen(clientToken: String) {
        val checkout = rememberPrimerCheckoutController(clientToken)

        PrimerCheckoutSheet(
            checkout = checkout,
            onEvent = { event ->
                when (event) {
                    is PrimerCheckoutEvent.Success -> navigateToConfirmation(event.checkoutData)
                    is PrimerCheckoutEvent.Failure -> {
                        Log.e("Checkout", "Failed: ${event.error.description}")
                    }
                }
            },
            onDismiss = { navigateBack() },
        )
    }
    ```
  </Tab>

  <Tab title="iOS">
    ```swift theme={"dark"}
    struct CheckoutView: View {
      let clientToken: String

      var body: some View {
        PrimerCheckout(
          clientToken: clientToken,
          primerSettings: PrimerSettings(paymentHandling: .auto),
          primerTheme: PrimerCheckoutTheme(
            colors: ColorOverrides(primerColorBrand: .blue)
          ),
          onCompletion: { state in
            switch state {
            case .success(let result):
              print("Payment: \(result.payment?.id ?? "")")
            case .failure(let error):
              print("Failed: \(error.errorId)")
            case .dismissed:
              print("Dismissed")
            default:
              break
            }
          }
        )
      }
    }
    ```
  </Tab>
</Tabs>

## How Components Communicate

Components communicate through:

1. **Context inheritance** - Child components receive context from their parents (e.g., card inputs receive form context from their parent card form)
2. **Events** - Components emit events that you can listen to for state changes
3. **Customization points** (Slots on Web, Composable lambdas on Android, Scope closures on iOS) - Allow you to inject custom content at specific points

<Info>
  For details on events, see the [Events guide](/checkout/primer-checkout/configuration/events).
</Info>

## Customization at Each Level

<Tabs>
  <Tab title="Web">
    * **`<primer-checkout>`** - SDK options, theming, global configuration
    * **`<primer-main>`** - Layout structure through customization points
    * **`<primer-payment-method>`** - Payment method-specific options
    * **`<primer-card-form>`** - Complete control over card form layout and styling
  </Tab>

  <Tab title="Android">
    * **`PrimerCheckoutSheet` / `PrimerCheckoutHost`** - Presentation mode and event handling
    * **`PrimerCheckoutSheetDefaults`** - Override default screens (splash, loading, success, error)
    * **`CardFormDefaults`** - Customize individual card form fields
    * **`PrimerTheme`** - Colors, typography, spacing, and border radius
  </Tab>

  <Tab title="iOS">
    * **`PrimerCheckout`** - Client token, settings, theme, and completion handling
    * **`PrimerCheckoutScope`** - Splash, loading, error screens, and container customization
    * **`PrimerPaymentMethodSelectionScope`** - Payment method list item and screen customization
    * **`PrimerCardFormScope`** - Card form fields, layout sections, and submit button
    * **`PrimerCheckoutTheme`** - Colors, typography, spacing, radius, and border widths
  </Tab>
</Tabs>

## See also

<CardGroup cols={2}>
  <Card title="Using Slots" icon="table-layout" href="/checkout/primer-checkout/build-your-ui/layout-customization">
    Learn how to customize layout with slots
  </Card>

  <Card title="Build a custom card form" icon="credit-card" href="/checkout/primer-checkout/guides-and-recipes/build-custom-card-form">
    Step-by-step tutorial for card form customization
  </Card>

  <Card title="Styles" icon="palette" href="/checkout/primer-checkout/build-your-ui/styling-customization">
    Customize appearance with CSS variables
  </Card>

  <Card title="SDK Reference" icon="code" href="/sdk/primer-checkout-web/components/primer-checkout">
    Detailed API documentation for all components
  </Card>
</CardGroup>
