Single-Page Checkout
Contact, shipping and payment in one scrolling form with a single place-order button.
3 frameworksIntermediate
A card-details form - number, name, expiry, CVC - that is UI only and charges nothing.
<!--
Card fields only, and only fields - this template does not tokenise, validate
or charge anything. The value is the plumbing: cc-number / cc-name / cc-exp /
cc-csc autocomplete tokens and inputMode="numeric" so the browser and password
managers fill the right box and phones show a number pad. The brand marks are
decorative inline SVG (aria-hidden), not real logos.
-->
<form class="w-full max-w-sm space-y-4 rounded-2xl border border-gray-200 bg-white p-5 sm:p-6 dark:border-gray-800 dark:bg-gray-950" action="#" method="post" novalidate>
<div class="flex items-center justify-between">
<h2 class="text-sm font-semibold text-gray-900 dark:text-gray-100">Payment details</h2>
<div class="flex gap-1" aria-hidden="true">
<span class="flex h-5 w-8 items-center justify-center rounded bg-gradient-to-r from-indigo-500 to-blue-600 text-[8px] font-bold text-white">VISA</span>
<span class="flex h-5 w-8 items-center justify-center rounded bg-gradient-to-r from-orange-500 to-red-500 text-[8px] font-bold text-white">MC</span>
</div>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300" for="pf-card">Card number</label>
<input class="mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder:text-gray-500 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" id="pf-card" name="cc-number" type="text" autocomplete="cc-number" inputmode="numeric" placeholder="1234 1234 1234 1234" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300" for="pf-name">Name on card</label>
<input class="mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder:text-gray-500 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" id="pf-name" name="cc-name" type="text" autocomplete="cc-name" placeholder="Ada Lovelace" />
</div>
<div class="grid grid-cols-2 gap-4">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300" for="pf-exp">Expiry</label>
<input class="mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder:text-gray-500 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" id="pf-exp" name="cc-exp" type="text" autocomplete="cc-exp" inputmode="numeric" placeholder="MM / YY" />
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300" for="pf-csc">CVC</label>
<input class="mt-1 block w-full rounded-lg border border-gray-300 bg-white px-3 py-2.5 text-sm text-gray-900 placeholder:text-gray-400 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:placeholder:text-gray-500 dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" id="pf-csc" name="cc-csc" type="text" autocomplete="cc-csc" inputmode="numeric" placeholder="123" />
</div>
</div>
<button class="inline-flex w-full items-center justify-center rounded-lg bg-blue-600 px-5 py-3 text-sm font-semibold text-white transition-colors hover:bg-blue-700 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-blue-600 focus-visible:ring-offset-2 focus-visible:ring-offset-white motion-reduce:transition-none dark:focus-visible:ring-blue-400 dark:focus-visible:ring-offset-gray-950" type="submit">Pay now</button>
<p class="text-center text-xs text-gray-500 dark:text-gray-400">Your payment details are never stored by this demo.</p>
</form>| Prop | Type | Default | Description |
|---|---|---|---|
payLabel | string | 'Pay now' | Pay label |
onSubmit | (e: FormEvent) => void | - | Called with the form's values when it is submitted. |
className | string | - | Additional classes merged onto the root element. |
This is plumbing, not a processor: the value is the `cc-number` / `cc-name` / `cc-exp` / `cc-csc` autocomplete tokens plus `inputMode="numeric"` so browsers and password managers fill the right box. The brand marks are decorative stand-ins, not real logos, and `onSubmit` defaults to a no-op.