Skip to content

Checkout

Checkout screens for a one-off order or a subscription, with an order summary in view.

Installation & usage

npx @youj/cli add commerce-subscription-checkout

Also installs alert, badge, button, card, collapse, counter, empty, field, icon-arrow-right, icon-check, icon-check-circle, icon-credit-card, icon-lock, icon-tag, icon-x, input, input-group, number-input, radio-group, reveal, segmented-control, select, separator, use-controllable-state, wizard, youj-core, youj-presets, youj-ui-core.

The CLI copies the block to blocks/commerce/subscription-checkout.tsx with every component it uses, so it’s yours to edit.

Every prop is optional and falls back to the demo, so it renders as you see it until you pass your own. Give it your data, rewrite or translate its strings through copy, and connect its actions:

subscriptionCheckout-view.tsx
'use client'

import { SubscriptionCheckout, type SubscriptionCheckoutProps } from '@/blocks/commerce/subscription-checkout'

export function SubscriptionCheckoutView({ plans, period, countries, promoCodes }: Pick<SubscriptionCheckoutProps, 'plans' | 'period' | 'countries' | 'promoCodes'>) {
  return (
    <SubscriptionCheckout
      plans={plans}
      period={period}
      countries={countries}
      promoCodes={promoCodes}
      copy={{ brand: 'Northwind' }}
      onPlanChange={(plan) => {
        // your code
      }}
      onPeriodChange={(period) => {
        // your code
      }}
      onSeatsChange={(seats) => {
        // your code
      }}
    />
  )
}

Reference

Props20 props, 4 types

Props

SubscriptionCheckout props
PropType
themeThemeInput

Wraps the page in this theme. Default: the theme around it.

–
copyPartial<SubscriptionCheckoutCopy>

Any of the checkout's strings, to rewrite or translate.

–
plansPlan[]

The plans to choose from.

default the demo's three

the demo's three
planstring

The chosen plan's id, controlled: pair it with onPlanChange.

–
defaultPlanstring

The plan chosen first, when the checkout owns it.

default 'pro'

'pro'
onPlanChange(plan: string) => void–
periodPeriod
'monthly''yearly'

The billing period, controlled: pair it with onPeriodChange.

–
defaultPeriodPeriod
'monthly''yearly'

The period first shown, when the checkout owns it.

default 'yearly'

'yearly'
onPeriodChange(period: Period) => void–
seatsnumber

The seat count, controlled: pair it with onSeatsChange.

–
defaultSeatsnumber

The seats first set, when the checkout owns them.

default 5

5
onSeatsChange(seats: number) => void–
countriesCountry[]

The countries you sell to, with the tax each adds.

default the demo's eight

the demo's eight
defaultPaymentPartial<Payment>

The payment form's starting values (a signed-in buyer's email and country, say).

–
brand{ name: string; logo?: ReactNode }

The product in the header: { name, logo? }. Default: copy.brand with its initial.

–
currencystring

An ISO 4217 code. Default: copy.currency ('USD').

–
localestring

A BCP 47 locale for prices. Default: copy.locale, else the app's locale (YoujProvider), else en-US.

–
promoCodesRecord<string, number>

Codes and the share each takes off, like { LAUNCH20: 0.2 }.

default demo

demo
onSubscribe(order: SubscriptionOrder) => unknown

Takes the order to your payment provider. Reject to stay on the step.

default demo

demo
onDone() => void

The confirmation's "Go to your workspace".

–

SubscriptionCountry

SubscriptionCountry props
PropType
codeRequiredstring–
nameRequiredstring–
taxLabelRequiredstring–
taxRateRequirednumber–

SubscriptionPayment

SubscriptionPayment props
PropType
emailRequiredstring–
holderRequiredstring–
cardRequiredstring–
expiryRequiredstring–
cvcRequiredstring–
countryRequiredstring–
postalRequiredstring–

SubscriptionPlan

SubscriptionPlan props
PropType
idRequiredstring–
nameRequiredstring–
descriptionRequiredstring–
priceRequirednumber

Per seat per month, billed monthly.

–
featuresRequiredstring[]–
popularboolean

Marked as the one most teams pick.

–

SubscriptionOrder

SubscriptionOrder props
PropType
planRequiredstring–
periodRequiredPeriod
'monthly''yearly'
–
seatsRequirednumber–
promostring–
totalRequirednumber–
paymentRequiredOmit<Payment, 'card' | 'cvc'> & { last4: string }–
Strings60 keys for copy

Strings

copy takes any of these keys; the rest keep their defaults. A key whose text holds a value (a count, a name) takes a function.

currencybrandsecuredemotitlesubtitlestepPlanstepPlanDescriptionstepPaymentstepPaymentDescriptionbillingmonthlyyearlysaveplanpopularperSeatseatsseatsHintplaceholderTitleplaceholderDescriptionemailholdercardcardPlaceholderexpiryexpiryPlaceholdercvccvcPlaceholdercountrypostalemailInvalidholderRequiredcardInvalidexpiryInvalidcvcInvalidpostalRequiredbacknextsubscribesubscribedsummaryseatLineyearlyDiscountpromopromoPlaceholderapplyremovePromopromoInvalidpromoAppliedsubtotaltaxtotalrenewsdoneTitledoneDescriptionreceiptpaidWithopenlocale
Built from17 components
Accessibilitylandmarks, headings, forms

Accessibility

Checkout has one h1 and puts the order summary under its own h2, with the order as a real list; fields are labelled. Subscription checkout wraps the page in main under a header, labels its plan choices, and announces the changing total in a live region (aria-live). Links and buttons are real a and button elements with the kit’s focus ring.