Skip to main content
This page documents @whop/elements@1.0.0-beta.3 and @whop/elements-react@1.0.0-beta.3.
Pre-release, not yet part of a stable release.
Mounts inside Payments. Pass props and callbacks through the create options or React props. Keep the created handle, or React ref, to call select().
Exclusive. PaymentElement is an alternative to CardElement or CardFields in this Payments handle. Mount one at a time. Destroy it before mounting another.
Mount inside <Payments>, which owns the charge and the confirmation token. <Payments> itself mounts inside <WhopElements>. It renders the method tiles for the charge and collects whatever the selected method declares, so a card, a wallet sheet and a bank redirect are the same one line.

Example data. Open the Playground.

Props

string[]
Controls display order in either layout. Listed types appear first in order. Unlisted types retain their relative order. Does not affect availability. Defaults to [].
{ billingDetails?: "full" | "minimal" | "never" | undefined; }
Controls billing-details collection. billingDetails: 'minimal' (default) follows each method’s matrix. Methods collect name and the complete country format by default. An override may collect only the declared minimum or nothing. For cards, the minimum is name on card, country, and postal code. 'full' requires name and the complete country format for every fresh method. 'never' hides the block. Pass the address to createConfirmationToken instead. The country selector includes only countries supported by the method and payment currency. With an installment plan selected, it narrows to the countries the plan serves — the billing country is the transaction country the charge processes under. It locks when only one is available. Defaults to {"billingDetails":"minimal"}.
"accordion" | "horizontal"
Picker layout. accordion (default) stacks methods and expands details inline. horizontal shows equal-width, non-scrolling tiles with selected details below. After four methods, a More tile opens a native selector. The method picked there occupies the final tile until the next selection. Selection and confirmation behave identically. Defaults to "accordion".
boolean
accordion only. Adds spacing and separate card styling between methods. Ignored when layout is horizontal. Defaults to false.
boolean
Whether to select the first offered method after resolution. The default true respects order and emits selected and change like a buyer interaction. It runs once before buyer interaction and does nothing when no method is offered. Set false to mount unselected. Independently, if an update removes the selected method, selection falls back to the first offered method. An already unselected element stays unselected. Defaults to true.

Events

Pass callbacks in the create options or React props.

onChange

Fires when selection changes. complete: true means the buyer selected a method and completed its card fields or required inputs. Use it to enable confirmation. method provides category, per-currency countries, and amount bounds for dependent UI such as country fields. supportsBuyerFee indicates whether to include Whop’s buyer service fee in the displayed total.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

Fires about 300 ms after the internal billing address changes. Use it for tax, shipping, or other address-dependent updates. country is an ISO 3166-1 alpha-2 code. The payload omits other address keys when empty or unused for that country. complete: true means the billing block is valid and complete. This event fires only while the payment element owns address collection. With fields.billingDetails: 'never', use your address source. With a mounted AddressElement, use its change event.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

Runs after the loading skeleton first paints and before onReady.Signature: (() => void)

onReady

Runs after the element’s first complete paint.Signature: (() => void)

onError

Runs when the element fails to load or crashes. The fallback remains visible. Use code for programmatic handling. sourceKey identifies a failed host-state source.Signature: ((e: { message: string; code?: string | undefined; sourceKey?: string | undefined; }) => void)

Methods

Call these on the handle returned by create, or through a React ref.

select

Select a method through the same path as a buyer interaction. For example, select('cashapp') expands the tile and emits selected and change. Cards remain complete: false until their fields are complete. Unknown, unavailable, or amount-gated methods reject with code METHOD_NOT_OFFERED. select(null) clears selection and emits change with complete: false. Use with autoSelect={false} for full external control.Signature: (input: string | null) => Promise<void>

mount

Mounts the element in target and starts loading. React components mount themselves.Signature: (target: string | HTMLElement) => void

destroy

Removes the element and releases its frame and subscriptions. You can call it more than once. React removes the element automatically.Signature: () => void

update

Merges new props into the mounted element. In React, change the component props instead.Signature: (options: Partial<PaymentElementProps>) => void

Styling

Style these parts through appearance.classes. Use camel case or kebab case for property names and include units. Page stylesheets can’t reach the element’s frame. The framework validates each declaration before injecting it.
In React, pass appearance to <Payments>. Set it globally with WhopElements({ appearance }).

Props

string[]
Method display order, with Stripe’s paymentMethodOrder semantics. Unlisted types keep their incoming relative order behind the listed ones. Also settable once on <Payments>.
(payload: PaymentChangePayload) => void
Fires on every selection and completeness change. Gate your submit button on complete.
StyleProp<ViewStyle>
Applied to the element’s outer View. For theming, prefer appearance.parts on the provider, which covers every element on this surface. Note the React Native part names are their own set today, not the web’s whop-* class names, so a web appearance object does not port across unchanged.
ReactNode
Rendered instead of the built-in skeleton while the element loads.
() => void
Fires once the element is interactive. <Payments> groups these, so its own onLoadingChange is usually the one you want.
(error: { message: string; code?: string }) => void
A load or configuration failure for this element. The element renders its own error face either way.

PaymentChangePayload

What onChange hands back:
  • complete: boolean: the selected method has everything it needs
  • type?: string: the selected method type, e.g. card
  • method?: { type, category, template, display_name }: the selected method’s matrix entry

States

Three skeleton rows until the method matrix lands, then the tiles. Selecting a tile expands its detail region beneath it. onChange reports complete when the selected method has everything it needs, which is what gates your submit button. A charge with no eligible method renders an explanatory empty state rather than nothing.

Good to know

  • Card numbers never pass through your code. The fields are PCI-isolated native inputs, and the SDK hands Whop a token, so your app stays out of PCI scope.
  • Apple Pay and Google Pay use the platform sheet through PKPaymentAuthorizationController and Google’s PaymentsClient. Apple Pay needs a merchant identifier: it comes from the account’s own Apple Pay registration, and applePayMerchantId on <Payments> overrides it, so the tile is hidden only when neither exists. Google Pay needs nothing from you; googlePayMerchantName only sets the name shown in the sheet, which defaults to Whop.
  • Redirect methods and 3D Secure open ASWebAuthenticationSession on iOS and Custom Tabs on Android. The system browser, never a WebView, so the issuer’s page stays outside your app’s trust boundary.
  • Set returnUrl on <Payments> to an https URL you host. The API refuses anything but https or loopback (PaymentsApi::ValidateReturnUrl), so a custom app scheme is not available here. You do not register a deep link: after the issuer redirects, handleNextAction polls the payment to rest and closes the browser itself.
Wrap your app in <WhopElements getToken={…}> once, then mount <Payments> around the elements. See Getting started and Appearance.