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

# Slot Architecture Explorer — Web

> Explore the component hierarchy and available slots in Primer Checkout for Web.

export const Badge = ({children, color = DS.color.brand}) => <span style={{
  fontSize: DS.font.xxs - 1,
  fontWeight: 700,
  padding: `1px ${DS.space.sm - 2}px`,
  borderRadius: DS.radius.sm,
  background: `${color}15`,
  color: color,
  textTransform: 'uppercase',
  letterSpacing: '0.3px',
  whiteSpace: 'nowrap'
}}>{children}</span>;

export const Panel = ({title, children, style}) => <div style={Object.assign({
  background: DS.color.bgSurface,
  border: `1px solid ${DS.color.border}`,
  borderRadius: DS.radius.lg,
  overflow: 'hidden'
}, style)}>
    {title && <div style={{
  padding: `${DS.space.sm}px ${DS.space.lg}px`,
  borderBottom: `1px solid ${DS.color.border}`,
  fontSize: DS.font.xxs,
  fontWeight: 700,
  textTransform: 'uppercase',
  letterSpacing: '1px',
  color: DS.color.textMuted,
  background: DS.color.bgSubtle
}}>
        {title}
      </div>}
    {children}
  </div>;

export const DS = {
  color: {
    brand: 'var(--ds-color-brand, #2f98ff)',
    brandLight: 'var(--ds-color-brand-light, #e8f2ff)',
    brandMuted: 'var(--ds-color-brand-muted, rgba(47, 152, 255, 0.12))',
    focus: 'var(--ds-color-brand, #2f98ff)',
    success: 'var(--ds-color-success, #1a8a5c)',
    successLight: 'var(--ds-color-success-light, #edf8f2)',
    successMuted: 'var(--ds-color-success-muted, rgba(26, 138, 92, 0.12))',
    warning: 'var(--ds-color-warning, #c47a20)',
    warningLight: 'var(--ds-color-warning-light, #fef6eb)',
    warningMuted: 'var(--ds-color-warning-muted, rgba(196, 122, 32, 0.12))',
    error: 'var(--ds-color-error, #c44040)',
    errorLight: 'var(--ds-color-error-light, #fef0f0)',
    errorMuted: 'rgba(196, 64, 64, 0.12)',
    purple: '#7c5cbf',
    purpleLight: '#f3effc',
    purpleMuted: 'rgba(124, 92, 191, 0.12)',
    text: 'var(--ds-color-text, #1c1b18)',
    textSecondary: 'var(--ds-color-text-secondary, #5c5953)',
    textMuted: 'var(--ds-color-text-muted, #9d9a92)',
    textDisabled: '#c5c2ba',
    border: 'var(--ds-color-border, #e4e2dd)',
    borderHover: 'var(--ds-color-border-hover, #d0cec8)',
    bgPage: 'var(--ds-color-bg-page, #f5f4f1)',
    bgSurface: 'var(--ds-color-bg-surface, #ffffff)',
    bgSubtle: 'var(--ds-color-bg-subtle, #fafaf8)',
    bgOverlay: 'rgba(0, 0, 0, 0.04)'
  },
  space: {
    xxs: 2,
    xs: 4,
    sm: 8,
    md: 12,
    lg: 16,
    xl: 20,
    xxl: 24,
    xxxl: 32
  },
  font: {
    xxs: 10,
    xs: 11,
    sm: 12,
    md: 13,
    base: 14,
    lg: 15,
    xl: 16,
    mono: "ui-monospace, 'SF Mono', SFMono-Regular, Menlo, Monaco, Consolas, monospace",
    sans: "system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif"
  },
  radius: {
    sm: 4,
    md: 8,
    lg: 12
  },
  transition: {
    fast: '120ms ease',
    normal: '200ms ease'
  }
};

export const SLOT_INFO = {
  'primer-checkout': {
    color: DS.color.brand,
    slots: [{
      name: 'main',
      default: 'primer-main',
      overridable: true
    }]
  },
  'primer-main': {
    color: DS.color.purple,
    slots: [{
      name: 'payments',
      default: 'vault + payment methods',
      overridable: true
    }, {
      name: 'checkout-complete',
      default: 'primer-checkout-complete',
      overridable: true
    }]
  },
  'primer-card-form': {
    color: DS.color.success,
    slots: [{
      name: 'card-form-content',
      default: 'built-in card form UI',
      overridable: true
    }]
  },
  'primer-vault-manager': {
    color: DS.color.textMuted,
    slots: [{
      name: 'vault-empty-state',
      default: 'built-in vault UI',
      overridable: true
    }, {
      name: 'submit-button',
      default: 'primer-vault-payment-submit',
      overridable: true
    }]
  },
  'primer-show-other-payments': {
    color: DS.color.textMuted,
    slots: [{
      name: 'show-other-payments-toggle-button',
      default: 'primer-collapsable',
      overridable: true
    }, {
      name: 'other-payments',
      default: 'primer-payment-method(s)',
      overridable: false
    }]
  },
  'primer-input-wrapper': {
    color: DS.color.warning,
    slots: [{
      name: 'label',
      default: 'primer-input-label',
      overridable: true
    }, {
      name: 'input',
      default: 'hosted input',
      overridable: false
    }, {
      name: 'error',
      default: 'primer-input-error',
      overridable: true
    }]
  },
  'primer-vault-cvv-input': {
    color: DS.color.warning,
    slots: [{
      name: 'label',
      default: '<primer-input-label>CVV</...>',
      overridable: true
    }]
  },
  'primer-error-message-container': {
    color: DS.color.error,
    slots: []
  },
  'primer-payment-method': {
    color: DS.color.textMuted,
    slots: []
  }
};

export const CONDITIONAL_RENDERING = [{
  component: 'primer-vault-manager',
  condition: 'Renders when vault is enabled and not in headless mode'
}, {
  component: 'primer-show-other-payments',
  condition: 'Shows accordion when vault has saved methods or showEmptyState is true'
}, {
  component: 'primer-checkout-complete',
  condition: 'Shown when sdkState.isSuccessful is true'
}, {
  component: 'primer-vault-cvv-input',
  condition: 'Shown when a vaulted card is selected and CVV recapture is required'
}];

export const SlotLine = ({name, defaultContent, overridable, color}) => <div style={{
  display: 'flex',
  alignItems: 'center',
  gap: DS.space.sm,
  margin: `${DS.space.sm}px 0 ${DS.space.xs + 2}px`,
  minWidth: 0
}}>
    <div style={{
  height: 0,
  width: DS.space.md,
  borderTop: `1px dashed ${color}50`,
  flexShrink: 0
}} />
    <Badge color={color}>slot: {name}</Badge>
    <span style={{
  fontSize: DS.font.xxs,
  color: DS.color.textMuted,
  fontFamily: DS.font.mono,
  whiteSpace: 'nowrap',
  overflow: 'hidden',
  textOverflow: 'ellipsis',
  minWidth: 0
}}>→ {defaultContent}</span>
    {overridable && <Badge color={DS.color.purple}>✎ overridable</Badge>}
    <div style={{
  height: 0,
  flex: '1 1 0',
  minWidth: DS.space.sm,
  borderTop: `1px dashed ${color}50`
}} />
  </div>;

export const CompNode = ({name, color, depth = 0, onClick, children, typeLabel, selected}) => {
  const [hovered, setHovered] = useState(false);
  const isActive = selected === name;
  return <div onClick={e => {
    e.stopPropagation();
    onClick?.(name);
  }} onMouseEnter={() => setHovered(true)} onMouseLeave={() => setHovered(false)} style={{
    background: isActive ? `${color}08` : hovered ? DS.color.bgSubtle : DS.color.bgPage,
    border: `2px solid ${isActive ? color : hovered ? DS.color.borderHover : DS.color.border}`,
    borderLeftWidth: 3,
    borderLeftColor: isActive ? color : hovered ? DS.color.borderHover : DS.color.border,
    borderRadius: DS.radius.md,
    padding: depth > 1 ? `${DS.space.sm}px ${DS.space.sm + 2}px` : `${DS.space.sm + 2}px ${DS.space.md}px`,
    margin: `${DS.space.xs}px 0`,
    cursor: onClick ? 'pointer' : 'default',
    transition: `border-color ${DS.transition.fast}, background ${DS.transition.fast}`,
    overflow: 'hidden',
    minWidth: 0
  }}>
      <div style={{
    fontFamily: DS.font.mono,
    fontWeight: 600,
    fontSize: depth > 1 ? DS.font.xs : DS.font.sm,
    color: isActive ? color : DS.color.textSecondary,
    display: 'flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
        <span>{name}</span>
        {typeLabel && <Badge color={color}>{typeLabel}</Badge>}
      </div>
      {children && <div style={{
    marginTop: DS.space.sm
  }}>{children}</div>}
    </div>;
};

export const PaymentMethodChip = ({name, type, color}) => <div style={{
  backgroundColor: DS.color.bgSubtle,
  border: `2px solid ${DS.color.border}`,
  borderRadius: DS.radius.md,
  padding: `${DS.space.xs + 2}px ${DS.space.sm + 2}px`,
  flex: 1,
  minWidth: 0
}}>
    <div style={{
  fontFamily: DS.font.mono,
  fontSize: DS.font.xxs,
  fontWeight: 600,
  color: DS.color.textSecondary,
  display: 'flex',
  alignItems: 'center',
  gap: DS.space.sm
}}>
      <span>{name}</span>
      <Badge color={color}>{type}</Badge>
    </div>
  </div>;

export const InputChip = ({name, color}) => <span style={{
  display: 'inline-block',
  padding: `${DS.space.xxs + 1}px ${DS.space.sm}px`,
  borderRadius: DS.radius.sm,
  fontFamily: DS.font.mono,
  fontSize: DS.font.xxs,
  background: `${color}15`,
  color: color,
  border: `1px solid ${color}30`,
  margin: 2
}}>{name}</span>;

export const SlotArchitectureExplorer = () => {
  const [selected, setSelected] = useState(null);
  const data = selected ? SLOT_INFO[selected] : null;
  return <div style={{
    display: 'grid',
    gridTemplateColumns: '1fr 280px',
    gap: DS.space.xl
  }}>
      <Panel title="Default Checkout Layout" style={{
    minWidth: 0,
    overflow: 'hidden'
  }}>
        <div style={{
    padding: DS.space.lg
  }}>
          <CompNode name="primer-checkout" color={DS.color.brand} typeLabel="root" onClick={setSelected} selected={selected}>
            <SlotLine name="main" defaultContent="primer-main" overridable={true} color={DS.color.purple} />

            <CompNode name="primer-main" color={DS.color.purple} typeLabel="layout" onClick={setSelected} selected={selected} depth={1}>
              <SlotLine name="payments" defaultContent="vault + payment methods" overridable={true} color={DS.color.success} />

              <CompNode name="primer-vault-manager" color={DS.color.textMuted} typeLabel="container" onClick={setSelected} selected={selected} depth={2}>
                <SlotLine name="vault-empty-state" defaultContent="built-in vault UI" overridable={true} color={DS.color.textMuted} />
                <SlotLine name="submit-button" defaultContent="primer-vault-payment-submit" overridable={true} color={DS.color.textMuted} />
              </CompNode>

              <CompNode name="primer-show-other-payments" color={DS.color.textMuted} typeLabel="container" onClick={setSelected} selected={selected} depth={2}>
                <SlotLine name="show-other-payments-toggle-button" defaultContent="primer-collapsable" overridable={true} color={DS.color.textMuted} />
                <SlotLine name="other-payments" defaultContent="primer-payment-method(s)" overridable={false} color={DS.color.textMuted} />

                <div style={{
    paddingLeft: DS.space.md
  }}>
                  <CompNode name="primer-payment-method" color={DS.color.textMuted} typeLabel="× N" onClick={setSelected} selected={selected} depth={3}>
                    <div style={{
    fontSize: DS.font.xxs,
    color: DS.color.textMuted,
    margin: `${DS.space.sm}px 0 ${DS.space.sm}px`,
    lineHeight: 1.5
  }}>
                      Renders one of the following based on <code style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xxs
  }}>managerType</code>:
                    </div>

                    <CompNode name="primer-card-form" color={DS.color.success} typeLabel="CARD" onClick={setSelected} selected={selected} depth={4}>
                      <SlotLine name="card-form-content" defaultContent="built-in card form" overridable={true} color={DS.color.success} />
                      <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: 3,
    paddingTop: 2
  }}>
                        <InputChip name="input-card-number" color={DS.color.warning} />
                        <InputChip name="input-card-expiry" color={DS.color.warning} />
                        <InputChip name="input-cvv" color={DS.color.warning} />
                        <InputChip name="input-card-holder-name" color={DS.color.warning} />
                        <InputChip name="card-form-submit" color={DS.color.error} />
                        <InputChip name="billing-address" color={DS.color.textMuted} />
                      </div>
                    </CompNode>

                    <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: DS.space.xs,
    marginTop: DS.space.sm
  }}>
                      <PaymentMethodChip name="primer-google-pay" type="NATIVE" color={DS.color.brand} />
                      <PaymentMethodChip name="primer-apple-pay" type="NATIVE" color={DS.color.brand} />
                      <PaymentMethodChip name="primer-paypal" type="NATIVE" color={DS.color.brand} />
                    </div>
                    <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: DS.space.xs,
    marginTop: DS.space.xs
  }}>
                      <PaymentMethodChip name="primer-klarna" type="KLARNA" color={DS.color.purple} />
                      <PaymentMethodChip name="primer-redirect-payment" type="REDIRECT" color={DS.color.warning} />
                    </div>
                  </CompNode>
                </div>
              </CompNode>

              <CompNode name="primer-error-message-container" color={DS.color.error} typeLabel="errors" onClick={setSelected} selected={selected} depth={2} />

              <SlotLine name="checkout-complete" defaultContent="primer-checkout-complete" overridable={true} color={DS.color.brand} />
              <div style={{
    border: `2px dashed ${DS.color.border}`,
    borderRadius: DS.radius.sm,
    padding: `${DS.space.sm}px ${DS.space.md}px`,
    fontSize: DS.font.xs,
    color: DS.color.textMuted,
    fontStyle: 'italic'
  }}>
                Your success screen — shown after payment completes
              </div>
            </CompNode>
          </CompNode>

          <div style={{
    marginTop: DS.space.lg
  }}>
            <div style={{
    fontSize: DS.font.xxs,
    fontWeight: 600,
    textTransform: 'uppercase',
    letterSpacing: '1px',
    color: DS.color.textMuted,
    marginBottom: DS.space.sm,
    display: 'flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              <span style={{
    width: 14,
    height: 0,
    borderTop: `2px dashed ${DS.color.borderHover}`
  }} />
              Utility component (not in default layout)
            </div>
            <div style={{
    border: `2px dashed ${DS.color.borderHover}`,
    background: DS.color.bgSubtle,
    borderRadius: DS.radius.md,
    padding: `${DS.space.sm + 2}px ${DS.space.md}px`
  }}>
              <div style={{
    fontFamily: DS.font.mono,
    fontWeight: 600,
    fontSize: DS.font.sm,
    color: DS.color.textMuted,
    display: 'flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
                <span>primer-payment-method-container</span>
                <Badge color={DS.color.textMuted}>utility</Badge>
              </div>
              <div style={{
    marginTop: DS.space.sm,
    fontSize: DS.font.xs,
    color: DS.color.textSecondary,
    lineHeight: 1.5
  }}>
                Filters and renders <code style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xxs
  }}>primer-payment-method</code> instances by type.
                Use in custom layouts with <code style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xxs
  }}>include</code> / <code style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xxs
  }}>exclude</code> props.
              </div>
              <div style={{
    display: 'flex',
    gap: DS.space.xs,
    marginTop: DS.space.sm,
    flexWrap: 'wrap'
  }}>
                {['include="PAYMENT_CARD,PAYPAL"', 'exclude="KLARNA"', 'disabled'].map(attr => <span key={attr} style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xxs,
    padding: `2px ${DS.space.sm}px`,
    borderRadius: DS.radius.sm,
    background: DS.color.bgSubtle,
    border: `1px solid ${DS.color.borderHover}`,
    color: DS.color.textMuted
  }}>{attr}</span>)}
              </div>
            </div>
          </div>

          <div style={{
    marginTop: DS.space.xl,
    paddingTop: DS.space.lg,
    borderTop: `1px solid ${DS.color.border}`
  }}>
            <div style={{
    fontSize: DS.font.xxs,
    fontWeight: 600,
    textTransform: 'uppercase',
    letterSpacing: '1px',
    color: DS.color.textMuted,
    marginBottom: DS.space.sm,
    display: 'flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              ⚡ Conditional rendering
            </div>
            <div style={{
    display: 'grid',
    gridTemplateColumns: 'repeat(auto-fit, minmax(280px, 1fr))',
    gap: DS.space.sm
  }}>
              {CONDITIONAL_RENDERING.map(item => <div key={item.component} style={{
    background: DS.color.bgSubtle,
    border: `1px solid ${DS.color.border}`,
    borderRadius: DS.radius.sm,
    padding: `${DS.space.sm + 2}px ${DS.space.md}px`
  }}>
                  <div style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.xs,
    fontWeight: 500,
    color: DS.color.text,
    marginBottom: DS.space.xs
  }}>
                    {item.component}
                  </div>
                  <div style={{
    fontSize: DS.font.xxs,
    color: DS.color.textSecondary,
    lineHeight: 1.4
  }}>
                    {item.condition}
                  </div>
                </div>)}
            </div>
          </div>

          <div style={{
    display: 'flex',
    flexWrap: 'wrap',
    gap: DS.space.lg,
    paddingTop: DS.space.lg,
    marginTop: DS.space.lg,
    borderTop: `1px solid ${DS.color.border}`,
    fontSize: DS.font.xs,
    color: DS.color.textMuted
  }}>
            <span style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              <span style={{
    width: 16,
    height: 12,
    borderRadius: 3,
    border: `2px solid ${DS.color.border}`,
    background: DS.color.bgSubtle
  }} />
              Component
            </span>
            <span style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              <span style={{
    width: 16,
    height: 12,
    borderRadius: 3,
    border: `2px dashed ${DS.color.borderHover}`,
    background: DS.color.bgSubtle
  }} />
              Utility / placeholder
            </span>
            <span style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              <span style={{
    width: 24,
    height: 0,
    borderTop: `1px dashed ${DS.color.purple}50`
  }} />
              <Badge color={DS.color.purple}>slot</Badge>
              Named slot
            </span>
            <span style={{
    display: 'inline-flex',
    alignItems: 'center',
    gap: DS.space.sm
  }}>
              <Badge color={DS.color.purple}>✎ overridable</Badge>
              Merchant can replace
            </span>
          </div>
        </div>
      </Panel>

      <Panel title="Component Details">
        <div style={{
    padding: DS.space.lg
  }}>
          {selected && data ? <div>
              <div style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.base,
    fontWeight: 600,
    color: data.color,
    marginBottom: DS.space.md
  }}>
                {selected}
              </div>

              {data.slots.length > 0 ? <div>
                  <div style={{
    fontSize: DS.font.xs,
    fontWeight: 600,
    color: DS.color.textSecondary,
    marginBottom: DS.space.sm
  }}>
                    Available Slots ({data.slots.length})
                  </div>
                  {data.slots.map(slot => <div key={slot.name} style={{
    padding: DS.space.sm + 2,
    background: DS.color.bgSubtle,
    borderRadius: DS.radius.sm,
    marginBottom: DS.space.sm,
    borderLeft: `3px solid ${data.color}`
  }}>
                      <div style={{
    fontFamily: DS.font.mono,
    fontSize: DS.font.sm,
    fontWeight: 600,
    color: data.color
  }}>
                        {slot.name}
                      </div>
                      <div style={{
    fontSize: DS.font.xs,
    color: DS.color.textMuted,
    marginTop: DS.space.xs
  }}>
                        Default: <span style={{
    fontFamily: DS.font.mono
  }}>{slot.default}</span>
                      </div>
                      {slot.overridable && <div style={{
    marginTop: DS.space.sm
  }}>
                          <Badge color={DS.color.purple}>✎ overridable</Badge>
                        </div>}
                    </div>)}
                </div> : <div style={{
    fontSize: DS.font.sm,
    color: DS.color.textMuted,
    fontStyle: 'italic'
  }}>
                  No named slots available.
                </div>}

              <button onClick={() => setSelected(null)} style={{
    marginTop: DS.space.lg,
    padding: `${DS.space.sm}px ${DS.space.md}px`,
    border: `1px solid ${DS.color.border}`,
    borderRadius: DS.radius.sm,
    background: DS.color.bgSurface,
    color: DS.color.textMuted,
    fontSize: DS.font.sm,
    cursor: 'pointer',
    width: '100%'
  }}>Clear Selection</button>
            </div> : <div style={{
    color: DS.color.textMuted,
    fontSize: DS.font.sm,
    fontStyle: 'italic'
  }}>
              Click a component on the left to view its slots and details.
            </div>}
        </div>
      </Panel>
    </div>;
};

<SlotArchitectureExplorer />

***

## Using Slots in Your Code

Slots are the primary mechanism for customizing layout in Primer Checkout. Each slot is a named placeholder where you can insert your own content.

```html theme={"dark"}
<primer-checkout client-token="your-client-token">
  <div slot="main">
    <!-- This content replaces the default main slot -->
    <primer-main>
      <div slot="payments">
        <!-- Custom payment methods layout -->
      </div>
    </primer-main>
  </div>
</primer-checkout>
```

<Tip>
  If you don't provide content for a slot, the component uses its default content. This lets you customize only the parts you need.
</Tip>

***

## Slot Reference

A complete reference of all named slots available in Primer Checkout components.

<AccordionGroup>
  <Accordion title="primer-checkout">
    | Slot   | Default Content |
    | ------ | --------------- |
    | `main` | `primer-main`   |
  </Accordion>

  <Accordion title="primer-main">
    | Slot                | Default Content                 |
    | ------------------- | ------------------------------- |
    | `payments`          | vault-manager + payment methods |
    | `checkout-complete` | `primer-checkout-complete`      |
  </Accordion>

  <Accordion title="primer-vault-manager">
    | Slot                | Default Content               |
    | ------------------- | ----------------------------- |
    | `vault-empty-state` | built-in vault UI             |
    | `submit-button`     | `primer-vault-payment-submit` |
  </Accordion>

  <Accordion title="primer-show-other-payments">
    | Slot                                | Default Content            |
    | ----------------------------------- | -------------------------- |
    | `show-other-payments-toggle-button` | `primer-collapsable`       |
    | `other-payments`                    | `primer-payment-method`(s) |
  </Accordion>

  <Accordion title="primer-card-form">
    | Slot                | Default Content       |
    | ------------------- | --------------------- |
    | `card-form-content` | built-in card form UI |
  </Accordion>

  <Accordion title="primer-vault-cvv-input">
    | Slot    | Default Content                                |
    | ------- | ---------------------------------------------- |
    | `label` | `<primer-input-label>CVV</primer-input-label>` |
  </Accordion>

  <Accordion title="primer-input-wrapper">
    | Slot    | Default Content      |
    | ------- | -------------------- |
    | `label` | `primer-input-label` |
    | `input` | hosted input element |
    | `error` | `primer-input-error` |
  </Accordion>
</AccordionGroup>

***

## Code Examples

Common patterns for customizing slots in Primer Checkout.

<AccordionGroup>
  <Accordion title="Custom main layout">
    Override the entire checkout content with your own UI:

    ```html theme={"dark"}
    <primer-checkout client-token="...">
      <div slot="main">
        <!-- Your custom checkout UI -->
      </div>
    </primer-checkout>
    ```
  </Accordion>

  <Accordion title="Custom card form layout">
    Rearrange the card form fields with your own layout:

    ```html theme={"dark"}
    <primer-card-form>
      <div slot="card-form-content" class="my-layout">
        <primer-input-card-number></primer-input-card-number>
        <div class="row">
          <primer-input-card-expiry></primer-input-card-expiry>
          <primer-input-cvv></primer-input-cvv>
        </div>
        <primer-card-form-submit>Pay Now</primer-card-form-submit>
      </div>
    </primer-card-form>
    ```
  </Accordion>

  <Accordion title="Custom vault submit button">
    Replace the default vault submit button:

    ```html theme={"dark"}
    <primer-vault-manager>
      <button slot="submit-button" type="submit">
        Pay with saved card
      </button>
    </primer-vault-manager>
    ```
  </Accordion>

  <Accordion title="Custom success screen">
    Show a custom message after successful payment:

    ```html theme={"dark"}
    <primer-checkout client-token="...">
      <primer-main slot="main">
        <div slot="checkout-complete">
          <h1>Thank you for your order!</h1>
          <p>Order confirmation sent to your email.</p>
        </div>
      </primer-main>
    </primer-checkout>
    ```
  </Accordion>
</AccordionGroup>

***

## See also

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

  <Card title="Layout with event handling" icon="bolt" href="/checkout/primer-checkout/build-your-ui/advanced-layout-customization">
    Build fully custom checkout experiences
  </Card>

  <Card title="Design tokens explorer" icon="droplet" href="/checkout/primer-checkout/build-your-ui/design-tokens-explorer">
    Explore CSS variables and styling
  </Card>
</CardGroup>
