skrewww

Forms

Credit Card Field

Credit Card Field is a compound UI control for card number, expiry, and CVC in one shell — visual pattern only, not a payment processor or PCI vault.

State (Default/Focused/Error/Disabled) — 4 variants

betaReact AvailableFigma AvailableDocs Partial
React last updated
2026-09-14
Documentation last updated
2026-09-14
Accessibility target
WCAG 2.2 AA (target)
Version
0.1.0-beta

Known open questions

  • Figma default TEXT shows masked demo digits (••••) — React does not mask PANs; apps must not treat UI masking as security.
  • No Size axis in Figma — shell matches Text Input md height.
  • Production card capture should prefer hosted/tokenized provider fields; this component is the visual pattern only.

Live preview

Compound shell: generic card icon + number + expiry + CVC. Values stay digit-only; spaces/slash are display-only.

Surface
Shape

Interactive

Card details

UI pattern only — not a payment processor. Prefer hosted provider fields for real capture.

Digits: / /

Default with synthetic filled value

Saved card

Error

Card details

Check the card details and try again.

Disabled

Card details

Read-only

Card details

Purpose

Credit Card Field is a compound UI control for card number, expiry, and CVC in one visually unified shell. It is a visual/input pattern only — not a payment processor, tokenizer, or PCI vault.

Anatomy

CreditCardField = fieldset/legend + shared shell (generic CreditCard icon + number input + divider + expiry input + divider + CVC input) + optional supporting/error text.

Variants and states

default · focused · error · disabled

When to use

When documenting or prototyping the joined card-details pattern. For production card capture, prefer a payment provider’s hosted/tokenized fields.

When not to use

When using Stripe Elements / Adyen / similar hosted card elements. Do not treat this React control as sufficient for PCI-sensitive production capture.

Accessibility

fieldset + legend for the group; each segment is a real text input with its own accessible name (number/expiry/CVC). Focus chrome is shell-level (:focus-within). Generic CreditCard icon is decorative (aria-hidden).

Keyboard behavior

Standard text editing in each segment. Tab moves between number, expiry, and CVC. Shell focus-within shows the Focused chrome.

Common mistakes

Treating this as one text input. Treating display spaces/slash as stored value. Assuming brand detection or payment authorization. Logging or persisting raw card digits.

Properties

Figma: State + Card Number / Expiry / CVC text. React: label, value/defaultValue/onValueChange ({number,expiry,cvc} digit-only), segment labels/placeholders, disabled, readOnly, required, error, supportingText.

Is this a payment integration?

No. It does not tokenize, authorize, store, or transmit card data. Prefer Stripe Elements / equivalent hosted fields for PCI-sensitive capture.

Does it detect Visa/Mastercard?

No. Figma uses a generic Icon/CreditCard deliberately — network logos are not reproduced.

Tokens used

component/radius/controlsemantic/border/defaultsemantic/focus-ringsemantic/action/dangercolor/neutral/200

Known limitation

Figma demo TEXT may show masked bullets — React does not mask PANs. No brand logos. No Luhn/network validation. /r deferred to CE-3. This component does not claim PCI compliance.

Component API

PropTypeDefaultDescription
labelstringVisible fieldset legend for the compound control.
value{ number: string; expiry: string; cvc: string }Controlled digit-only values (no spaces/slash). Display formatting is presentation-only.
defaultValue{ number: string; expiry: string; cvc: string }Uncontrolled initial digit-only values.
onValueChange(value: { number; expiry; cvc }) => voidFires with digit-only values after edits/paste.
numberLabelstring"Card number"Accessible name for the number segment.
expiryLabelstring"Expiry"Accessible name for the expiry segment.
cvcLabelstring"CVC"Accessible name for the CVC segment.
disabledbooleanfalseDisables all segments and dims the shell.
readOnlybooleanfalseRead-only segments; shell remains interactive for focus.
requiredbooleanfalseMarks the group and each segment required.
errorstringError message; sets invalid chrome on the shared shell.
supportingTextstringHelp text when no error is present.

React example

Copy React example
import { useState } from "react";
import { CreditCardField } from "@/components/ui/CreditCardField";

export function Example() {
  const [value, setValue] = useState({ number: "", expiry: "", cvc: "" });
  return (
    <CreditCardField
      label="Card details"
      value={value}
      onValueChange={setValue}
      supportingText="UI pattern only — use a payment provider for real card capture."
    />
  );
}