Skip to content
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.

Purpose

Credit Card Field is a compound credit card input field pattern for card number, expiry, and CVC in one visually unified shell. It is a payment form card details 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 a payment form’s joined card-details input. 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.

What validation does Credit Card Field perform?

Consumers can supply an error string to show invalid chrome and message text. Skrewww does not run Luhn checks or card-network validation. This remains a UI/input pattern for card details — not a payment processor.

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
labelstring—Visible 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 }) => void—Fires 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.
errorstring—Error message; sets invalid chrome on the shared shell.
supportingTextstring—Help 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."
    />
  );
}