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

# PaymentElement

> The drop-in payment method picker: shows the payment methods this seller accepts for the charge — filtered live by currency, amount, and seller configuration — and collects what the chosen method needs: card fields, billing address, method-specific inputs, and any required disclosures. Drive your pay button off the `change` event, call `payments.createConfirmationToken()` on click, confirm the token server-side with your secret key, then pass any pending step to `payments.handleNextAction(...)`. The `addressChange` event reports the billing address it collects as the buyer fills it in, so your checkout can quote tax, rate shipping, or update anything else that depends on the address. Two arrangements via `layout`: a stacked list (default) or a horizontal tile row.

<Info>**Upcoming.** These docs cover unreleased development, ahead of any published release. Use the channel picker at the top of the sidebar for the docs of a published release.</Info>

*In development, not yet part of a stable release.*

Belongs to the [`Payments`](/elements/upcoming/payments/overview) group. Render `<PaymentElement />` inside it (React), or call `payments.create('payment', { … })` on the handle (vanilla). Consumer props and `on<Event>` callbacks both go in the create options / JSX props.

<Note>**Exclusive.** When using `PaymentElement`, you can't mount `CardElement` or `CardFields` in the same Payments handle. These are alternatives: mount one at a time, and destroy it to mount another.</Note>

## Preview

A live, interactive demo of this element with sample data:

<div data-whop-demo-shell style={{ position: "relative", minHeight: "320px", transition: "min-height 200ms ease" }}>
  <div data-whop-demo-skeleton style={{ position: "absolute", inset: "0", borderRadius: "12px", background: "rgba(140, 140, 140, 0.12)", pointerEvents: "none", transition: "opacity 200ms ease" }} />

  <div data-whop-demo-native="element:payments/payment" data-whop-elements-version="" style={{ position: "relative" }} />
</div>

## Usage

<div data-whop-usage="payments/payment">
  <CodeGroup>
    ```tsx React theme={null}
    import { WhopElements, Payments, PaymentElement } from "@whop/elements-react";
    import { loadWhop } from "@whop/elements";

    function Example() {
      return (
        <WhopElements elements={loadWhop()}>
          <Payments /* options */>
            <PaymentElement onChange={(payload) => console.log("change", payload)} onAddressChange={(payload) => console.log("addressChange", payload)} />
          </Payments>
        </WhopElements>
      );
    }
    ```

    ```html Vanilla theme={null}
    <script src="https://js.whop.cloud/elements/amber/elements.js" data-whop-elements></script>
    <script type="module">
      const payments = window.WhopElements().payments.create({ /* options */ });
      payments.create('payment', {
        onChange: (payload) => console.log("change", payload),
        onAddressChange: (payload) => console.log("addressChange", payload)
      }).mount('#payments-payment');
    </script>
    ```
  </CodeGroup>
</div>

## Props

<ResponseField name="fields" type="{ billingDetails?: &#x22;full&#x22; | &#x22;minimal&#x22; | &#x22;never&#x22; | undefined; }">
  Which internal collection blocks render. `billingDetails: 'minimal'` (default) collects each method's DECLARED payment minimum — exactly the billing fields the method's matrix entry declares (card: name on card, country, postal code — never a street address; most redirect and wallet methods declare nothing and render no block at all). `'full'` opts every fresh method into name plus the complete country format — for hosts who want a full billing address (tax-style collection is a checkout concern, not a payment requirement). `'never'` hides the block — pass the address in `createConfirmationToken({ billingDetails })` instead. The block's country select offers only the countries the method supports for the charge currency (a single-country method locks it). Defaults to `{"billingDetails":"minimal"}`.
</ResponseField>

<ResponseField name="layout" type="&#x22;accordion&#x22; | &#x22;horizontal&#x22;">
  Presentation of the method picker: 'accordion' (default) stacks the methods in a vertical list, each expanding its detail inline; 'horizontal' lays the methods out as a row of equal-width tiles (never scrolling — beyond four methods the row ends in a More tile whose native selector lists the rest, and a method picked there holds the last tile spot until the next pick) with the selected method's detail below. Selection and confirm behavior are identical in both. Defaults to `"accordion"`.
</ResponseField>

<ResponseField name="separated" type="boolean">
  Accordion layout only: render each method as its own visually separate card with spacing between items, instead of the fused list. Ignored while `layout` is 'horizontal'. Defaults to `false`.
</ResponseField>

<ResponseField name="order" type="string[]">
  Display ordering of the methods, in every layout: listed types render first in the given order, unlisted types keep their relative order after them. Presentation only — never affects which methods are available. Defaults to `[]`.
</ResponseField>

<ResponseField name="autoSelect" type="boolean">
  Select the first offered method automatically once the methods resolve (default true) — respects `order` and emits `selected` + `change` exactly like a click. One-shot: it never re-fires after the buyer interacts, and it does nothing when no method is offered. Set false to mount with nothing selected. Separately from this flag, when a live charge update drops the SELECTED method off the list the selection falls back to the first offered method (an element with nothing selected stays blank). Defaults to `true`.
</ResponseField>

## Events

Pass a callback in the create options (or React prop) to receive these.

### `onChange`

The selection changed — `complete: true` means a method is chosen (and, for card, its fields are filled; for methods declaring required inputs, those are filled and valid) so the confirm can run; drive your pay button off it. `method` carries the selected entry's matrix metadata (category, per-currency country list, amount bounds) so your page can react — e.g. narrow its own country field. `supportsBuyerFee` says whether a charge on the chosen method carries Whop's buyer service fee, so a checkout can re-price the total it shows before the buyer pays.

**Signature:** `((payload: { complete: boolean; type?: string | undefined; supportsBuyerFee?: boolean | undefined; method?: { type: string; category: string; template: string; display_name: string; countries: ({ country: string; min_amount: number | null; max_amount: number | null; })[]; min_amount: number | null; max_amount: number | null; } | undefined; }) => void)`

### `onAddressChange`

The billing address the element collects itself changed — quote tax off it, rate your own shipping off it, or drive any address-dependent part of your page off it. Carries the whole postal address: `country` (ISO2) always, plus `line1`, `line2`, `city`, `state` and `postal_code` whenever the country's format collects them (a key is absent when the form has no value for it — several countries have no state or no postal code at all). Debounced \~300ms and emitted only on a real change, so it maps one-to-one onto a quote. `complete: true` means the whole billing block is filled and valid. Fires only while the element collects the address itself — with `fields.billingDetails: 'never'`, or beside a live address element (which collapses the internal block), drive your quote off that surface's own `change` instead.

**Signature:** `((payload: { complete: boolean; address: { line1?: string | undefined; line2?: string | undefined; city?: string | undefined; state?: string | undefined; postal_code?: string | undefined; country: string; }; }) => void)`

### `onLoaderStart`

Fired the moment the element's own loading skeleton has painted inside its frame. This is the earliest point a consumer-managed loading state can hand off without ever exposing a blank. Always precedes `onReady`; most consumers only need `onReady`.

**Signature:** `(() => void)`

### `onReady`

Fired once the element has booted and painted its first complete frame.

**Signature:** `(() => void)`

### `onError`

Fired when the element fails to load or crashes; the element shows its own error fallback. `message` is human-readable; framework refusals also carry `code` (e.g. `HOST_SOURCE_FAILED`, with `sourceKey` naming the failed hostState key) so hosts can switch on codes, never message text.

**Signature:** `((e: { message: string; code?: string | undefined; sourceKey?: string | undefined; }) => void)`

## Methods

Call these on the element handle, which is the return of `create` (vanilla) or the component `ref` (React).

### `select`

Select a payment method imperatively. `select('cashapp')` runs the same path a buyer's click does — the tile expands, `selected` and `change` fire (a card selection stays `complete: false` until its fields are filled). A type that isn't offered — unknown, seller-disabled, or amount-gated off the list — refuses with `code: 'METHOD_NOT_OFFERED'`. `select(null)` clears the selection, emitting `change { complete: false }`. Pair with `autoSelect={false}` (which mounts the element blank) for full external control of the selection.

**Signature:** `(input: string | null) => Promise<void>`

### `mount`

Place the element on the page: appends its container to `target` (a CSS selector or an element) and starts loading. Nothing renders until this is called. React consumers never call it; the component mounts itself.

**Signature:** `(target: string | HTMLElement) => void`

### `destroy`

Remove the element from the page and release its frame and subscriptions. Safe to call more than once. React consumers never call it; unmounting the component does it.

**Signature:** `() => void`

### `update`

Change this element's consumer props after mount, and it re-renders with the merged props. React consumers never call it; updating the JSX props does the same.

**Signature:** `(options: Partial<PaymentElementProps>) => void`

## Styling

Each part below is a stable class name, safe to depend on. Restyle a part by mapping its class to a **style declaration object** under `appearance.classes` (properties camelCase or kebab-case, values as strings with units, the same shape as React's `style` prop). The element renders in its own frame, so page stylesheets can't reach it: these declarations are sanitized against a safe-property allowlist and injected inside the frame for you.

| Class                                 | Targets                                                                                                                                                                         |
| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `.whop-Address`                       | The address form root                                                                                                                                                           |
| `.whop-AddressErrorSummary`           | The summary line shown when validation reveals missing or invalid fields                                                                                                        |
| `.whop-AddressField`                  | One field cell in the address form                                                                                                                                              |
| `.whop-AddressFieldError`             | The error line under an address field (full layout)                                                                                                                             |
| `.whop-AddressFieldInput`             | A text input in the address form                                                                                                                                                |
| `.whop-AddressFieldInputInvalid`      | Added to an address input while it fails validation                                                                                                                             |
| `.whop-AddressFieldInvalid`           | Added to a compact field cell while it fails validation                                                                                                                         |
| `.whop-AddressFieldLabel`             | The label above an address field (full layout)                                                                                                                                  |
| `.whop-AddressFieldSelect`            | A select (country, state, organization type) in the address form                                                                                                                |
| `.whop-AddressLine2Toggle`            | The "Add address line 2" text button shown while line 2 is collapsed                                                                                                            |
| `.whop-AddressManualEntry`            | The "Enter address manually" text button below the collapsed form — expands the full country format                                                                             |
| `.whop-AddressSuggestion`             | One suggestion row in the autocomplete overlay                                                                                                                                  |
| `.whop-AddressSuggestionActive`       | Added to the keyboard/pointer-active suggestion row                                                                                                                             |
| `.whop-AddressSuggestionManual`       | The "Enter address manually" row closing the suggestions list                                                                                                                   |
| `.whop-AddressSuggestions`            | The autocomplete suggestions overlay anchored to the address line 1 field                                                                                                       |
| `.whop-AddressSuggestionsEmpty`       | The quiet line shown when the query settled with no address matches                                                                                                             |
| `.whop-CardField`                     | One card field cell — number, expiry, or CVC                                                                                                                                    |
| `.whop-CardFieldError`                | The Invalid / Incomplete message under a card field                                                                                                                             |
| `.whop-CardFieldGroup`                | The grouped card fields — number on top, expiry and CVC below                                                                                                                   |
| `.whop-CardFieldInput`                | The bordered input container around a PCI field                                                                                                                                 |
| `.whop-CardFieldInputFocused`         | Added to the input container while its field is focused                                                                                                                         |
| `.whop-CardFieldInputInvalid`         | Added to the input container while its field is invalid or incomplete                                                                                                           |
| `.whop-CardLabel`                     | The "Card information" label above the field group                                                                                                                              |
| `.whop-Payment`                       | The payment element root                                                                                                                                                        |
| `.whop-PaymentBillingBlock`           | The payment element's internal billing address block                                                                                                                            |
| `.whop-PaymentCardFields`             | The inline card fields panel                                                                                                                                                    |
| `.whop-PaymentDetailIcon`             | The template icon beside the detail region's explainer                                                                                                                          |
| `.whop-PaymentDetailRegion`           | The expanded detail region for a selected method — collection surfaces first (inline card fields, declared inputs), then the explainer and disclosure lines as the bottom block |
| `.whop-PaymentDetailSubtext`          | The consent subtext under the explainer on wallet methods                                                                                                                       |
| `.whop-PaymentDetailText`             | The detail region's explainer line                                                                                                                                              |
| `.whop-PaymentError`                  | The error pane shown when methods cannot load or none are available                                                                                                             |
| `.whop-PaymentFieldError`             | The Invalid message under a declared input                                                                                                                                      |
| `.whop-PaymentFieldInput`             | A declared method input in the detail region                                                                                                                                    |
| `.whop-PaymentFieldInputInvalid`      | Added to a declared input while its value fails the declared format                                                                                                             |
| `.whop-PaymentFieldLabel`             | The label above a declared method input in the detail region                                                                                                                    |
| `.whop-PaymentMandateLink`            | The mandate terms link inside the mandate notice                                                                                                                                |
| `.whop-PaymentMandateNotice`          | The mandate authorization notice on methods whose matrix config declares a mandate                                                                                              |
| `.whop-PaymentMethod`                 | One payment method — the row plus its expanding detail region                                                                                                                   |
| `.whop-PaymentMethodDetail`           | The expanding region that reveals the selected method's detail — inline card fields, explainer, or declared inputs                                                              |
| `.whop-PaymentMethodIcon`             | The method icon on a row                                                                                                                                                        |
| `.whop-PaymentMethodLabel`            | The method display name on a row                                                                                                                                                |
| `.whop-PaymentMethodMoreSelect`       | The invisible native select stretched over the More tile                                                                                                                        |
| `.whop-PaymentMethodMoreTile`         | The compact overflow tile ending the capped tile row — stacked overflow-method icons over a chevron, its native select lists the remaining methods                              |
| `.whop-PaymentMethodPanel`            | The selected method's detail panel below the tile row (horizontal layout)                                                                                                       |
| `.whop-PaymentMethodRadio`            | The radio indicator on a method row                                                                                                                                             |
| `.whop-PaymentMethodRadioSelected`    | Added to the radio indicator while its method is selected                                                                                                                       |
| `.whop-PaymentMethodRow`              | The clickable payment method row                                                                                                                                                |
| `.whop-PaymentMethodRowSelected`      | Added to the method row while it is the selected method                                                                                                                         |
| `.whop-PaymentMethods`                | The payment method list                                                                                                                                                         |
| `.whop-PaymentMethodSeparated`        | Added to a method item while it renders as its own separated card                                                                                                               |
| `.whop-PaymentMethodsSeparated`       | Added to the method list while separated accordion items are on                                                                                                                 |
| `.whop-PaymentMethodTile`             | One method tile in the horizontal tile row                                                                                                                                      |
| `.whop-PaymentMethodTileRow`          | The method tile row (horizontal layout) — never scrolls; beyond the tile cap the overflow methods live in the compact More tile                                                 |
| `.whop-PaymentMethodTileSelected`     | Added to a method tile while it is the selected method                                                                                                                          |
| `.whop-PaymentMoreRow`                | The "N more payment methods" expander row                                                                                                                                       |
| `.whop-PaymentSavedMethod`            | One saved payment method specifically — carries PaymentMethod too                                                                                                               |
| `.whop-PaymentSavedMethodHint`        | The saved method's trailing detail — a card's expiry                                                                                                                            |
| `.whop-PaymentSavedMethodRow`         | The clickable saved method row specifically — carries PaymentMethodRow too                                                                                                      |
| `.whop-PaymentSavedMethodRowSelected` | The selected marker on a saved method row specifically                                                                                                                          |
| `.whop-PaymentSavedMethods`           | The saved-methods list specifically — carries PaymentMethods too, so one rule styles both lists                                                                                 |
| `.whop-PaymentSavedMethodSeparated`   | The separated marker on a saved method specifically                                                                                                                             |
| `.whop-PaymentSavedMore`              | The control that fetches the next page of saved payment methods                                                                                                                 |
| `.whop-PaymentSavedMoreSpinner`       | The spinner shown while the next page of saved payment methods loads                                                                                                            |
| `.whop-PaymentSaveNotice`             | The save-for-future-purchases consent line closing the detail region                                                                                                            |
| `.whop-PaymentSettlementNotice`       | The settlement-window hint on methods whose matrix config declares one                                                                                                          |

```ts theme={null}
const payments = whop.payments.create({
  appearance: {
    classes: {
      'whop-Address': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressErrorSummary': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressField': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldError': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldInput': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldInputInvalid': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldInvalid': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldLabel': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressFieldSelect': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressLine2Toggle': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressManualEntry': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressSuggestion': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressSuggestionActive': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressSuggestionManual': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressSuggestions': { borderRadius: '8px', fontWeight: '600' },
      'whop-AddressSuggestionsEmpty': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardField': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardFieldError': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardFieldGroup': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardFieldInput': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardFieldInputFocused': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardFieldInputInvalid': { borderRadius: '8px', fontWeight: '600' },
      'whop-CardLabel': { borderRadius: '8px', fontWeight: '600' },
      'whop-Payment': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentBillingBlock': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentCardFields': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentDetailIcon': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentDetailRegion': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentDetailSubtext': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentDetailText': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentError': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentFieldError': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentFieldInput': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentFieldInputInvalid': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentFieldLabel': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMandateLink': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMandateNotice': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethod': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodDetail': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodIcon': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodLabel': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodMoreSelect': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodMoreTile': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodPanel': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodRadio': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodRadioSelected': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodRow': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodRowSelected': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethods': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodSeparated': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodsSeparated': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodTile': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodTileRow': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMethodTileSelected': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentMoreRow': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethod': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethodHint': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethodRow': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethodRowSelected': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethods': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMethodSeparated': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMore': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSavedMoreSpinner': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSaveNotice': { borderRadius: '8px', fontWeight: '600' },
      'whop-PaymentSettlementNotice': { borderRadius: '8px', fontWeight: '600' }
    }
  }
});

// restyle live at any point, the same shape through update()
payments.update({
  appearance: { classes: { 'whop-Address': { fontWeight: '700' } } }
});
```

In React, pass the same object as the `appearance` prop on `<Payments>`; `appearance` also applies globally at `WhopElements({ appearance })`.
