Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Credit Card Field Form Block for React

A card as one joined control: number, expiry and CVC in a single group with one focus ring, a brand from the first digits, auto-advance, errors that name the part, and only the brand and last four kept after Save.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Take a card with this credit card form for React with Base UI. A compact header sits over a hairline frame with a plus mark on each corner, in cells on a hairline. The card is one joined control built from Input Group: number, expiry and CVC in a single bordered group with one focus ring around it. The number is grouped as you type (4-4-4-4, or 4-6-5 for Amex), a brand tile and the brand's name appear from the first digits, a complete number moves focus to the expiry and a complete expiry to the CVC, and Backspace on an empty part goes back. The first part that is wrong is named under the group ("Check the card number", "This card has expired", "The CVC has 4 digits on this card"). A name and a postal code follow. Save keeps only the brand and the last four ("Visa ending 4242" with a Vi tile) and wipes every digit. There is no drawn card face. For tipping, donation and payment forms that sit in front of a provider's hosted fields.

FAQ

Can I use this to take real card payments?

No, and the code says so. It checks a card in the tab's memory (brand by the first digits, the Luhn sum, the expiry against a fixed month) so you can see the pattern. A real page never lets card digits reach its own code: it uses the fields your payment provider hosts, an iframe of theirs, and this layout, labels and error wording around them. Nothing here is sent, stored or charged.

Which card works in the demo?

The test number 4242 4242 4242 4242 with any future expiry (the check is against October 2026) and any three digits; the "Use the test card" button fills it. A number that fails the Luhn sum, an expiry in the past, a month above 12 or a CVC of the wrong length each says so under the group and marks that part aria-invalid.

How do auto-advance and the keyboard work?

When the number reaches its brand's length and passes the Luhn sum, focus moves to the expiry; when the expiry has four digits and is valid, to the CVC. Only typing at the end advances, so editing the middle never jumps. Backspace in an empty expiry or CVC goes back to the part before with the caret at its end, and the caret stays with its digits while the number is regrouped. Paste works too: spaces and slashes are ignored.

What does Save keep?

Only the brand and the last four digits: "Visa ending 4242". The number, expiry, CVC, name and postal code are cleared from state, and the form is replaced in place by the saved card with a Replace card button, so the panel never changes height. Replace card returns an empty form.

What stays local, and how do I connect it for real?

Everything: Save says "Saved in this demo. Nothing was sent or charged." To connect it for real, mount your provider's hosted number, expiry and CVC fields in the group's place, keep the name and postal code fields, and send the provider's token, never digits, to your server.

How do I connect it to react-hook-form or TanStack Form?

Keep card digits out of the form library entirely: the hosted fields own them. With react-hook-form, register only the name and the postal code, and pass the provider's result to your submit handler.

  • Pro

    Payment Method Form

    Checkout and address

    A payment form where the method decides the fields: card, bank transfer with an IBAN grouped as you type and checked for length and mod-97, or a wallet, in one grid cell so nothing moves.

  • Pro

    Address Form with ZIP Help

    Checkout and address

    A six-column address grid that never changes size: street, an apartment line behind a quiet button, city, a state select and a ZIP code that fills the city and state from a typed table of six.

  • Pro

    A national-number field joined to a country menu that formats the digits for the chosen country as you type, checks the count per country and shows how the number would be stored.

  • Pro

    One-Time Code Input Form

    Numbers and pickers

    A six-slot confirmation code in two groups of three with its behaviours in view: paste fills all six and checks at once, a wrong code is marked, counted and cleared, and a resend button waits 30 seconds.

  • Pro

    A quantity field that sells in cases of six: typing a number snaps it up to a whole case on leaving, the keys and buttons move one case or five, and the line total is worked out in whole cents.

  • Pro

    A combobox of 20 countries in four areas, each with a two-letter tile and calling code, where four are out of reach with the reason in the row and a band gives what a parcel to the chosen country needs.