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-checkoutAlso 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:
'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
}}
/>
)
}Description
Take customers from choosing a subscription plan to payment, with a running order summary that updates as they choose.
Guide shoppers through contact details, shipping and payment with the order summary beside the form. Pick it for a one-off order.
Code
Subscription Checkout, the Subscription checkout story: the files youj add writes.
blocks/commerce
Reference
Props20 props, 4 types
Props
| Prop | Type | |
|---|---|---|
theme | ThemeInputWraps the page in this theme. Default: the theme around it. | – |
copy | Partial<SubscriptionCheckoutCopy>Any of the checkout's strings, to rewrite or translate. | – |
plans | Plan[]The plans to choose from. default the demo's three | the demo's three |
plan | stringThe chosen plan's id, controlled: pair it with | – |
defaultPlan | stringThe plan chosen first, when the checkout owns it. default 'pro' | 'pro' |
onPlanChange | (plan: string) => void | – |
period | Period'monthly''yearly'The billing period, controlled: pair it with | – |
defaultPeriod | Period'monthly''yearly'The period first shown, when the checkout owns it. default 'yearly' | 'yearly' |
onPeriodChange | (period: Period) => void | – |
seats | numberThe seat count, controlled: pair it with | – |
defaultSeats | numberThe seats first set, when the checkout owns them. default 5 | 5 |
onSeatsChange | (seats: number) => void | – |
countries | Country[]The countries you sell to, with the tax each adds. default the demo's eight | the demo's eight |
defaultPayment | Partial<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: | – |
currency | stringAn ISO 4217 code. Default: | – |
locale | stringA BCP 47 locale for prices. Default: | – |
promoCodes | Record<string, number>Codes and the share each takes off, like default demo | demo |
onSubscribe | (order: SubscriptionOrder) => unknownTakes the order to your payment provider. Reject to stay on the step. default demo | demo |
onDone | () => voidThe confirmation's "Go to your workspace". | – |
SubscriptionCountry
| Prop | Type | |
|---|---|---|
codeRequired | string | – |
nameRequired | string | – |
taxLabelRequired | string | – |
taxRateRequired | number | – |
SubscriptionPayment
| Prop | Type | |
|---|---|---|
emailRequired | string | – |
holderRequired | string | – |
cardRequired | string | – |
expiryRequired | string | – |
cvcRequired | string | – |
countryRequired | string | – |
postalRequired | string | – |
SubscriptionPlan
| Prop | Type | |
|---|---|---|
idRequired | string | – |
nameRequired | string | – |
descriptionRequired | string | – |
priceRequired | numberPer seat per month, billed monthly. | – |
featuresRequired | string[] | – |
popular | booleanMarked as the one most teams pick. | – |
SubscriptionOrder
| Prop | Type | |
|---|---|---|
planRequired | string | – |
periodRequired | Period'monthly''yearly' | – |
seatsRequired | number | – |
promo | string | – |
totalRequired | number | – |
paymentRequired | Omit<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.
currencybrandsecuredemotitlesubtitlestepPlanstepPlanDescriptionstepPaymentstepPaymentDescriptionbillingmonthlyyearlysaveplanpopularperSeatseatsseatsHintplaceholderTitleplaceholderDescriptionemailholdercardcardPlaceholderexpiryexpiryPlaceholdercvccvcPlaceholdercountrypostalemailInvalidholderRequiredcardInvalidexpiryInvalidcvcInvalidpostalRequiredbacknextsubscribesubscribedsummaryseatLineyearlyDiscountpromopromoPlaceholderapplyremovePromopromoInvalidpromoAppliedsubtotaltaxtotalrenewsdoneTitledoneDescriptionreceiptpaidWithopenlocaleBuilt 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.