Theme studio

Design a theme, preview it live, then export it. Saved in this browser.

Quick picks #10b981
Generated scale
50100200300400500600700800900
Some text is below AA

CardForm

  • Stable
  • WCAG 2.2 evidence
  • RTL

A form for entering a payment card. Built on React Aria Form and TextField: every field has a visible label tied to its input, and the errors are inline, with an icon and text, linked with aria-describedby and shown after a field loses focus or the form is submitted. A submit with errors announces how many fields need attention and moves focus to the first one (WCAG 1.3.1, 3.3.1, 3.3.2, 4.1.2, 4.1.3). The Figma states are not props: Empty, Typing (focus border), Valid (a check in the number box once it is complete and passes the checksum) and Error (a message under the field, for example "This card has expired") follow from what is typed. Typing formats as you go (groups of four, MM/YY) without blocking paste or autofill (3.3.7, 3.3.8); the fields carry the cc-number, cc-exp, cc-csc and cc-name autocomplete tokens (1.3.5); digits are monospaced and stay left-to-right in right-to-left pages. At 320 px the expiry and CVC fields stack (1.4.10). The form never stores or logs card data: it only hands the values to onSubmit. Do not use it to keep card data in your own system; use your payment provider's hosted fields where possible. Consumer duties: translated labels, the secure note wording, and what happens after submit.

import { CardForm } from "@nexera-ui/react";
Loading example…
11
examples
18
props
2
live controls
1
platform
15
WCAG criteria
2
blocks use it

Try every prop. Copy the code.

Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.

Loading…
isDisabled
children
Generated code
import { CardForm } from "@nexera-ui/react";

<CardForm />

Examples 10

The same examples as Storybook, rendered live. Open Code to copy one.

Typing

Figma State=Typing: a card number half typed, with the focus border on the field (focus is set when the story loads).

Loading example…

Valid

Figma State=Valid: a complete, valid card. The number box shows the network and a check.

Loading example…

Expired

Figma State=Error: the expiry is in the past, so after the form is submitted the field shows its message ("This card has expired") with an icon and the danger border, and focus moves to it.

Loading example…

All errors

Submitting an empty form shows every error, announces how many fields need attention and focuses the first one.

Loading example…

Disabled

isDisabled disables all fields, for example while the payment is being processed.

Loading example…

Custom network tile

renderNetwork puts your own logo in the 38 x 24 px tile; the default shows the network's name.

Loading example…

Submitting

Submit a valid card: onSubmit receives the normalised values and the network. Enter in any field submits.

Loading example…

Translated

Every text is a prop: translate labels (the messages, placeholders and the screen reader summary too).

Loading example…

Narrow container

At 18 rem the expiry and CVC fields stack; from 20 rem they sit side by side.

Loading example…

Right to left

Right-to-left: labels and the name field follow the page direction; card number, expiry and CVC stay left-to-right.

Loading example…

Props 18

Press "Try it" on a card to load that prop into the playground.

18 props shown

valueNexera
CardFormValues

The values (controlled). Use with onChange. number is digits only, expiry is MM/YY while typed, cvc digits.

Default –
defaultValueNexera
Partial<CardFormValues>

The values on first render (uncontrolled). Leave out the fields that start empty.

Default –
onChangeNexera
(values: CardFormValues) => void

Called with the new values whenever a field changes (the number as digits, without spaces).

Default –
onSubmitNexera
(values: CardFormValues & { network: CardNetwork; }) => void

Called when the form is submitted and every field is valid, with the normalised values. When something is wrong the form shows the errors, announces them, and moves focus to the first invalid field instead. Hand the values straight to your payment provider's client; never log or store them.

Default –
isDisabledNexera
boolean

Disables all fields.

Default false
labelsNexera
Partial<CardFormLabels>

Replaces any of the visible texts, messages and placeholders (translate them). Missing keys keep the English default.

Default –
secureNoteNexera
ReactNode

The note under the fields. Say who stores the details. Pass null to hide it.

Default Card details are encrypted and stored by our payment provider, not by us.
renderNetworkNexera
(network: CardNetwork) => ReactNode

Content of the network tile in the card number box, for example your logo of the network. It receives the detected network; the tile shows once the number's first digits are recognised. By default the tile holds the network's name as text.

Default –
todayNexera
Date

The date used to decide whether the expiry is in the past. Defaults to now; set it in tests and stories so that results do not depend on the day.

Default –
childrenNexera
ReactNode

Content after the note, for example the submit button: <Button type="submit">Save card</Button>.

Default –
classNameNexera
string

Extra classes for the form, merged last so they win over the defaults.

Default –
autoCapitalizeReact Aria
"off" | "none" | "on" | "sentences" | "words" | "characters"

Controls whether inputted text is automatically capitalized and, if so, in what manner. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autocapitalize).

Default –
roleReact Aria
"search" | "presentation"

An ARIA role override to apply to the form element.

Default –
aria-labelReact Aria
string

Defines a string value that labels the current element.

Default –
aria-labelledbyReact Aria
string

Identifies the element (or elements) that labels the current element.

Default –
aria-describedbyReact Aria
string

Identifies the element (or elements) that describes the object.

Default –
styleReact Aria
CSSProperties

The inline [style](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style) for the element.

Default –
idReact Aria
string

The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).

Default –

* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.

Accessible by default.

Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.

WCAG 2.2 evidence

13 direct · 2 supporting
  • 1.1.1Non-text ContentLevel A · tested directly
  • 1.3.1Info and RelationshipsLevel A · tested directly
  • 1.3.2Meaningful SequenceLevel A · supporting test
  • 1.3.5Identify Input PurposeLevel AA · tested directly
  • 1.4.1Use of ColorLevel A · tested directly
  • 1.4.10ReflowLevel AA · supporting test
  • 2.1.1KeyboardLevel A · tested directly
  • 3.1.2Language of PartsLevel AA · tested directly
  • 3.3.1Error IdentificationLevel A · tested directly
  • 3.3.2Labels or InstructionsLevel A · tested directly
  • 3.3.3Error SuggestionLevel AA · tested directly
  • 3.3.7Redundant EntryLevel A · tested directly
  • 3.3.8Accessible Authentication (Minimum)Level AA · tested directly
  • 4.1.2Name, Role, ValueLevel A · tested directly
  • 4.1.3Status MessagesLevel AA · tested directly

Fits any width.

Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.

0 px · drag the corner

Styling hooks

Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.

Usage
<CardForm className="shadow-sm" />

Used in blocks

Related components