> ## 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.

# PaymentMethodsDefaults

> Pre-built sub-components for custom payment method layouts

<Warning>
  Primer Checkout iOS SDK is currently in **beta** (v3.0.0-beta.1).
  The API is subject to change before the stable release.
</Warning>

`PaymentMethodsDefaults` is a public enum (used as a namespace) providing the pre-built `@ViewBuilder` content that [`PrimerPaymentMethods`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) renders when you omit a slot. Use these helpers inside your own slots to mix custom and default content, or as a reference for the default look and feel.

```swift theme={"dark"}
@available(iOS 15.0, *)
public enum PaymentMethodsDefaults
```

<Info>
  Each helper is the default value for the matching `PrimerPaymentMethods` slot. The component falls back to `PaymentMethodsDefaults.header($0)`, `PaymentMethodsDefaults.method($0, onSelect: $1)`, and `PaymentMethodsDefaults.emptyState($0)` when those slots are not supplied.
</Info>

## Builders

| Builder               | Description                                                                  |
| --------------------- | ---------------------------------------------------------------------------- |
| `header(_:)`          | Default "Choose payment method" header styled with the current theme         |
| `method(_:onSelect:)` | Payment method row with icon, name, optional surcharge, and selection action |
| `emptyState(_:)`      | Message displayed when no payment methods are available                      |

## header

```swift theme={"dark"}
public static func header(_ session: PrimerSelectionSession) -> PaymentMethodsHeaderContent
```

Renders the section title using the theme's [typography](/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/typography-tokens) and [color tokens](/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/color-tokens), with the header accessibility trait applied.

| Parameter | Type                     | Description                                                                                               |
| --------- | ------------------------ | --------------------------------------------------------------------------------------------------------- |
| `session` | `PrimerSelectionSession` | The active selection session. Accepted to match the slot closure signature; the default header is static. |

The `session` parameter exists only so this helper matches the `header` slot's closure signature — the default header does not read from it.

## method

```swift theme={"dark"}
public static func method(
    _ method: CheckoutPaymentMethod,
    onSelect: @escaping () -> Void
) -> PaymentMethodRowContent
```

Renders a tappable row for a single payment method, including its icon, display name, and any surcharge.

| Parameter  | Type                    | Description                                                                                             |
| ---------- | ----------------------- | ------------------------------------------------------------------------------------------------------- |
| `method`   | `CheckoutPaymentMethod` | The payment method data to display                                                                      |
| `onSelect` | `@escaping () -> Void`  | Callback invoked when the row is tapped. `PrimerPaymentMethods` wires this to `session.select(method)`. |

## emptyState

```swift theme={"dark"}
public static func emptyState(_ session: PrimerSelectionSession) -> PaymentMethodsEmptyContent
```

Rendered automatically by [`PrimerPaymentMethods`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) when `session.state.paymentMethods` is empty.

| Parameter | Type                     | Description                                                                                                    |
| --------- | ------------------------ | -------------------------------------------------------------------------------------------------------------- |
| `session` | `PrimerSelectionSession` | The active selection session. Accepted to match the slot closure signature; the default empty state is static. |

## Return types

Each builder returns a concrete public view type so it can serve as a `@ViewBuilder` default argument. You can use these types directly when composing your own layouts.

| Type                          | Returned by           | Description                         |
| ----------------------------- | --------------------- | ----------------------------------- |
| `PaymentMethodsHeaderContent` | `header(_:)`          | The default section header view     |
| `PaymentMethodRowContent`     | `method(_:onSelect:)` | A single default payment method row |
| `PaymentMethodsEmptyContent`  | `emptyState(_:)`      | The default empty-state view        |

```swift theme={"dark"}
@available(iOS 15.0, *)
public struct PaymentMethodsHeaderContent: View

@available(iOS 15.0, *)
public struct PaymentMethodRowContent: View

@available(iOS 15.0, *)
public struct PaymentMethodsEmptyContent: View
```

## Using defaults inside custom slots

Reuse a default builder for one part of the list while customizing another. Here the default header and empty state are kept, but each row is replaced with a branded row:

```swift theme={"dark"}
import SwiftUI
import PrimerSDK

struct CustomPaymentMethodsView: View {
    var body: some View {
        PrimerPaymentMethods(
            method: { method, onSelect in
                Button(action: onSelect) {
                    HStack {
                        if let icon = method.icon {
                            Image(uiImage: icon)
                                .resizable()
                                .scaledToFit()
                                .frame(width: 24, height: 24)
                        }
                        Text(method.name)
                        Spacer()
                        if let surcharge = method.formattedSurcharge {
                            Text(surcharge)
                                .foregroundColor(.secondary)
                        }
                    }
                    .padding()
                }
            }
        )
    }
}
```

Because the `header` and `emptyState` slots are omitted, `PrimerPaymentMethods` falls back to `PaymentMethodsDefaults.header` and `PaymentMethodsDefaults.emptyState`.

You can also call a default builder explicitly — for example, to render the default row while wrapping it in your own container:

```swift theme={"dark"}
PrimerPaymentMethods(
    method: { method, onSelect in
        PaymentMethodsDefaults.method(method, onSelect: onSelect)
            .padding(.horizontal)
            .background(Color(.secondarySystemBackground))
            .cornerRadius(12)
    }
)
```

<Tip>
  The `header` and `emptyState` slots pass you the [`PrimerSelectionSession`](/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/payment-methods-session), so you can branch on `session.state` to show custom content while still falling back to a default builder when appropriate.
</Tip>

## See also

<CardGroup cols={2}>
  <Card title="PrimerPaymentMethods" icon="list" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods">
    The slot-based payment method list these defaults power.
  </Card>

  <Card title="PrimerSelectionSession" icon="hand-pointer" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/payment-methods-session">
    Session that exposes the available methods and the select action.
  </Card>

  <Card title="VaultedPaymentMethods" icon="vault" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/vaulted-payment-methods">
    Saved payment methods and their own default sub-components.
  </Card>

  <Card title="CardFormDefaults" icon="credit-card" href="/docs/sdk/ios-checkout/v3.0.0-beta/api/card-form/card-form-defaults">
    The equivalent default sub-components for the card form.
  </Card>
</CardGroup>
