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

# Shape Tokens

> Corner radius, border width, and component size override tokens

> [!WARNING]
>
> Primer Checkout iOS SDK is currently in **beta** (v3.0.0-beta.8).
> The API is subject to change before the stable release.

Shape tokens control the geometry of Primer Checkout components: how rounded their corners are, how thick their borders are, and how large their fixed-dimension elements (icons, touch targets) render.

There are three override structs, each passed to the matching parameter of [`PrimerCheckoutTheme`](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/primer-theme):

| Struct | `PrimerCheckoutTheme` parameter | Controls |
| - | - | - |
| `RadiusOverrides` | `radius` | Corner radius scale |
| `WidthOverrides` | `width` | Border / stroke thickness |
| `SizeOverrides` | `sizes` | Fixed component dimensions |

Every property is an optional `CGFloat?`. Values you leave as `nil` fall back to the SDK's internal design tokens, so you only override what you need.

> [!NOTE]
>
> All three structs are `Equatable` and annotated `@available(iOS 15.0, *)`, matching the platform minimum for Primer Checkout.

## RadiusOverrides

Corner radius scale, in points. Property names match the SDK's internal `DesignTokens`.

```swift theme={"dark"}
@available(iOS 15.0, *)
public struct RadiusOverrides: Equatable {
    public let primerRadiusXsmall: CGFloat?
    public let primerRadiusSmall: CGFloat?
    public let primerRadiusMedium: CGFloat?
    public let primerRadiusLarge: CGFloat?

    public init(
        primerRadiusXsmall: CGFloat? = nil,
        primerRadiusSmall: CGFloat? = nil,
        primerRadiusMedium: CGFloat? = nil,
        primerRadiusLarge: CGFloat? = nil
    )
}
```

| Token | Type | Default | Description |
| - | - | - | - |
| `primerRadiusXsmall` | `CGFloat?` | 2 | Subtle rounding for the smallest elements |
| `primerRadiusSmall` | `CGFloat?` | 4 | Input fields, the saved-card CVV field, the inline card network selector, the country picker's search field, the ACH mandate box and the QR code |
| `primerRadiusMedium` | `CGFloat?` | 8 | Buttons, payment method rows, saved-card rows, the error screen button and Klarna options |
| `primerRadiusLarge` | `CGFloat?` | 12 | Container of the saved payment methods section |

## WidthOverrides

Border and stroke thickness, in points. Each token is named for the field state it styles.

```swift theme={"dark"}
@available(iOS 15.0, *)
public struct WidthOverrides: Equatable {
    public let primerWidthDefault: CGFloat?
    public let primerWidthFocus: CGFloat?
    public let primerWidthError: CGFloat?
    public let primerWidthSelected: CGFloat?

    public init(
        primerWidthDefault: CGFloat? = nil,
        primerWidthFocus: CGFloat? = nil,
        primerWidthError: CGFloat? = nil,
        primerWidthSelected: CGFloat? = nil
    )
}
```

| Token | Type | Default | Description |
| - | - | - | - |
| `primerWidthDefault` | `CGFloat?` | 1 | Resting border of input fields (also when disabled), payment method rows, saved-card rows, outlined buttons, the inline card network selector, the error screen button, the QR code view and Klarna options |
| `primerWidthFocus` | `CGFloat?` | 2 | Border of a focused input field, including the saved-card CVV field |
| `primerWidthError` | `CGFloat?` | 2 | Border of an input field in error, including the saved-card CVV field |
| `primerWidthSelected` | `CGFloat?` | 2 | Border of a selected saved payment method and the selected Klarna category |

## SizeOverrides

Fixed component dimensions, in points. Used for icons, touch targets, and other elements with an intrinsic size.

```swift theme={"dark"}
@available(iOS 15.0, *)
public struct SizeOverrides: Equatable {
    public let primerSizeSmall: CGFloat?
    public let primerSizeMedium: CGFloat?
    public let primerSizeLarge: CGFloat?
    public let primerSizeXlarge: CGFloat?
    public let primerSizeXxlarge: CGFloat?
    public let primerSizeXxxlarge: CGFloat?

    public init(
        primerSizeSmall: CGFloat? = nil,
        primerSizeMedium: CGFloat? = nil,
        primerSizeLarge: CGFloat? = nil,
        primerSizeXlarge: CGFloat? = nil,
        primerSizeXxlarge: CGFloat? = nil,
        primerSizeXxxlarge: CGFloat? = nil
    )
}
```

| Token | Type | Default | Description |
| - | - | - | - |
| `primerSizeSmall` | `CGFloat?` | 16 | Card icon in the card payment method button and the minimum height of the surcharge badge in the card number field |
| `primerSizeMedium` | `CGFloat?` | 20 | Field error icon, Klarna option selection indicator and the saved-card delete icon |
| `primerSizeLarge` | `CGFloat?` | 24 | Brand icon in a saved payment method row of `PrimerVaultedPaymentMethods` |
| `primerSizeXlarge` | `CGFloat?` | 32 | Not used by any component |
| `primerSizeXxlarge` | `CGFloat?` | 40 | Tap target of the saved-card delete button (never smaller than 44, so values under 44 have no visible effect) |
| `primerSizeXxxlarge` | `CGFloat?` | 56 | Size of the success screen's checkmark icon |

## Overriding shape tokens

Pass any combination of the three structs to `PrimerCheckoutTheme`. Unset properties inherit the SDK defaults.

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

let theme = PrimerCheckoutTheme(
    radius: RadiusOverrides(
        primerRadiusMedium: 12,
        primerRadiusLarge: 20
    ),
    sizes: SizeOverrides(
        primerSizeLarge: 28,
        primerSizeXxlarge: 48
    ),
    width: WidthOverrides(
        primerWidthDefault: 1.5,
        primerWidthFocus: 2.5
    )
)
```

Apply the theme on the prebuilt modal by passing it to `primerTheme`:

```swift theme={"dark"}
struct CheckoutView: View {
    let clientToken: String

    var body: some View {
        PrimerCheckout(
            clientToken: clientToken,
            primerTheme: theme
        ) { state in
            handle(state)
        }
    }
}
```

When you embed the composable views inline, pass the theme to the [`PrimerCheckoutSession`](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/primer-checkout-session) instead. The composable views resolve the merged tokens from the session.

```swift theme={"dark"}
struct InlineCheckoutView: View {
    @StateObject private var session: PrimerCheckoutSession

    init(clientToken: String) {
        _session = StateObject(
            wrappedValue: PrimerCheckoutSession(clientToken: clientToken, theme: theme)
        )
    }

    var body: some View {
        ScrollView {
            PrimerCardForm()
        }
        .primerCheckoutSession(session) { state in
            handle(state)
        }
    }
}
```

> [!TIP]
>
> Because every token is optional, you can override a single value, for example `RadiusOverrides(primerRadiusMedium: 12)`, and leave the rest of the scale untouched. Combine shape overrides with [color tokens](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/color-tokens.md) and the other override structs on `PrimerCheckoutTheme` to build a complete custom appearance.

## See also

> [card] [PrimerTheme](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/primer-theme.md)
>
> Assemble shape, color, spacing, and typography overrides into a theme.

> [card] [Color Tokens](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/color-tokens.md)
>
> Override brand, semantic, text, border, and icon colors.

> [card] [Spacing Tokens](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/spacing-tokens.md)
>
> Override the spacing scale used for layout and padding.

> [card] [Typography Tokens](https://primer.io/docs/sdk/ios-checkout/v3.0.0-beta/api/theming/typography-tokens.md)
>
> Override font family, weight, size, and line height per text style.


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