DOB Input

Reads a birth date and age back as it is typed and catches this year typed by habit, future dates and impossible ages, so birth dates aren't saved wrong.

StopsBirth year typed as this year

Installation

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

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

Usage

dob-input-usage.tsx
import { DobInput } from "@/components/ui/dob-input"

<DobInput label="Your date of birth" hint="For example, 27 3 1990" defaultValue="2026-03-14" today="2026-10-13" />

What it catches

  • This year typed as the birth year (age 0)
  • Future dates and implausible ages (minAge, maxAge)
  • A day typed into the month box
  • Pasted dates that could be read two ways
  • Under-age sign-ups, with the date the person becomes eligible

Props

DobInput props
PropTypeDefault
label

Legend for the group.

string"Date of birth"
hint

Hint under the legend, e.g. "For example, 27 3 1990".

string—
value

Controlled value as `YYYY-MM-DD`, or `""` while incomplete.

string—
defaultValue

Initial value when uncontrolled.

string""
onValueChange

Called with `YYYY-MM-DD` once the parts make a real past date, else `""`, plus the age.

(value: string, age?: number) => void—
order

Order of the boxes.

"dmy" | "mdy" | "ymd""dmy"
minAge

Block anyone younger than this, with the date they become old enough.

number—
maxAge

Ages above this are flagged as a likely year typo.

number120
allowInfants

Allow babies born this year (e.g. a child's record) without a warning.

booleanfalse
today

"Today" as `YYYY-MM-DD`. Defaults to the user's local date once mounted.

string—
locale

Locale for month names and dates.

string"en-IN"
partLabels

Box labels.

Record<Part, string>{ day: "Day", month: "Month", year: "Year" }
messages

Override any message.

Partial<DobMessages>—

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

Accessibility

  • Day, month and year each have a <label>, and are described by a shared status
  • aria-invalid on errors; Backspace in an empty part moves to the previous part
  • Focus moves between parts as each one is completed

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

Limitations

This is a UX guard rail. Enforce on the server: Re-check age eligibility on the server; a client-side date check can be bypassed.

  • Plausibility checks only; it can't verify a real birth date
  • Field order follows the `order` prop or locale; check it matches your users

What it stops

Birth year typed as this year

Also known as

date of birth · dob · birthday · age verification · dd/mm/yyyy · kyc · pan · 18+

Field type

Dependencies

Pairs well with