Card Expiry Input

Masks a card expiry as MM/YY and reads it back as a date, catching month 13, a year typed first or a card that expires before the next renewal.

StopsPayment declined on card expiry

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/card-expiry-input.json

The files land in your project. They're yours to edit.

Usage

card-expiry-input-usage.tsx
import { CardExpiryInput } from "@/components/ui/card-expiry-input"

<CardExpiryInput label="Expiry date" defaultValue="28/10" today={today} />

What it catches

  • Impossible months (13, 00) and the year typed first
  • A four-digit year, and YYYY-MM autofill
  • An expired card
  • A card that expires before the next renewal date you pass
  • Expiries implausibly far in the future (maxYears)

Props

CardExpiryInput props
PropTypeDefault
label

Visible label.

string"Expiry date"
value

Controlled value, as shown (MM/YY).

string—
defaultValue

Initial value when uncontrolled.

string""
onValueChange

Called with the formatted text, plus `{ month, year }` once it is a valid, unexpired date.

(value: string, expiry: { month: number; year: number } | null) => void—
today

"Today" for the expiry checks. Defaults to the visitor's clock, read after mount.

Date—
renewsOn

Next date the saved card will be charged. A card that runs out first gets a warning.

Date—
maxYears

Expiries further out than this many years are flagged as a likely wrong year.

number20
locale

Locale for the dates read back.

string"en-GB"
messages

Override any of the default messages.

Partial<typeof CARD_EXPIRY_MESSAGES>—

* required. Also accepts the native props of <input> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Visible <label>; aria-invalid when invalid and aria-describedby to an aria-live="polite" status
  • Errors use role="alert"
  • Fix buttons have visible text

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

  • Checks the date only; the issuer decides whether the card is valid
  • "Today" is the visitor's clock unless you pass `today`

What it stops

Payment declined on card expiry

Also known as

card expiry · expiry date · mm/yy · credit card · debit card · checkout · payment form · valid thru

Field type

Dependencies

Pairs well with