> ## 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.8).
> The API is subject to change before the stable release.

`PaymentMethodsDefaults` is a public enum (used as a namespace) providing the pre-built `@ViewBuilder` content that [`PrimerPaymentMethods`](https://primer.io/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
```

> [!NOTE]
>
> 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.

## Builders

| Builder | Description |
| - | - |
| `header(_:)` | Default "Choose payment method" header styled with the current theme |
| `method(_:onSelect:)` | Default tappable row for one payment method, styled per payment method type, that calls `onSelect` when tapped |
| `emptyState(_:)` | Message displayed when no payment methods are available |
| `unavailable()` | Empty placeholder rendered when no `PrimerSelectionSession` is in the environment |

## header

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

Renders the section title using the theme's [typography](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/typography-tokens.md) and [color tokens](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/color-tokens.md), 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. The row's content and VoiceOver label depend on the payment method type:

| Payment method type | Row content | VoiceOver label |
| - | - | - |
| Card | The card icon and the localized "Pay with card" title | "Pay with card" |
| Apple Pay | Apple's native Apple Pay button | The system Apple Pay label |
| Klarna | The Klarna logo inside the localized "Pay with Klarna" text | "Pay with Klarna" |
| Any other method | Its backend logo. Without a logo, the row shows `method.buttonText`, or `method.name` when there is no button text. | "Pay with" followed by `method.buttonText`, or `method.name` when there is no button text |

The default row does not display a surcharge. To show one, read `method.formattedSurcharge` in your own `method` slot, as in the [example below](#using-defaults-inside-custom-slots).

| 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`](https://primer.io/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. |

## unavailable

```swift theme={"dark"}
public static func unavailable() -> some View
```

Rendered by [`PrimerPaymentMethods`](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods) instead of its slots when no [`PrimerSelectionSession`](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/payment-methods-session) is in the environment. That is the case when the view is not inside `.primerCheckoutSession(_:)`, or when the session has not reached `.ready` yet. It returns an `EmptyView`, so the list occupies no space.

## Return types

Each slot builder returns a concrete public view type so it can serve as a `@ViewBuilder` default argument. These types have no public initializer. To get an instance, call the matching builder. You can still use the type name, for example as a property type or a return type.

| 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`](https://primer.io/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.

## See also

> [card] [PrimerPaymentMethods](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/primer-payment-methods.md)
>
> The slot-based payment method list these defaults power.

> [card] [PrimerSelectionSession](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/payment-methods-session.md)
>
> Session that exposes the available methods and the select action.

> [card] [VaultedPaymentMethods](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/payment-methods/vaulted-payment-methods.md)
>
> Saved payment methods and their own default sub-components.

> [card] [CardFormDefaults](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/card-form/card-form-defaults.md)
>
> The equivalent default sub-components for the card form.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.