Skip to content

PaymentMethods

Choose how to pay — one picker for the cart, an unpaid order and an invoice alike.

import { PaymentMethods } from "@evolve-storefront/commerce-ui/payment-methods";

Renders inside AddressConfigProvider.

Design notes

Keyed by internalId, not id: with provider it is the pair a payment mutation needs back. An empty list is a real answer and says so. options is not rendered — a sub-choice is a second selection, passed back through arguments. data-component is payment-methods everywhere, so scope it with a container.

Preview

DefaultOpen in Storybook ↗

Usage

Each method's logo, from the brand: the framework sends no image. The name stays the label, so the logo is decorative and the radio is still named "iDEAL".

const logos = { ideal: idealLogo, card: cardLogo };
<PaymentMethods
methods={methods}
value={selected}
onValueChange={setPaymentMethod}
renderIcon={(method) => logos[method.internalId] ? <img src={logos[method.internalId]} alt="" /> : null}
/>;

Props

PropTypeDescription
methodsreadonly PaymentMethod[]
onValueChange(method: PaymentMethodInput) => void

Hands over the method in the shape the mutation takes, rather than an id the caller would have to look back up.

value?string | null

The chosen method, by internalId.

isPending?boolean
emptyState?ReactNode

Rendered when nothing is offered for this amount, buyer and device.

More

A domain can say it better than a generic default can — an invoice's reason differs from a cart's — so the fallback is deliberately plain.

name?string

The radio group's name. Only matters where two pickers share a form, which nothing does today; defaulted so a caller need not think about it.

renderIcon?((method: PaymentMethod) => ReactNode)

A method's logo, shown at the end of its row. The framework sends no image, so the brand maps internalId to its own asset; the name stays the label, so a logo is decorative (alt=""). Return null for a method without one.

invalid?boolean

Marks the group, for a submit that needs a method and has none.

Any other props go to the root element, like on a plain HTML element.

Examples

Hands Over The Provider PairThe identity is internalId + provider, not id.
<PaymentMethods
methods={methods}
value={chosen?.internalId ?? null}
onValueChange={setChosen}
/>
Open in Storybook ↗