# Birth Date Field

> A typed date of birth that cannot be in the future or implausibly old, and that shows the age it implies so a typo in the year is caught straight away. Use this when a form asks for a date of birth and a typo in the year should be obvious.

A shadcn/ui block from the [@tealmac](https://ui.tealmac.com/?utm_source=shadcn.exchange) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/tealmac/birth-date-field).

- Page, with a live preview: https://shadcn.exchange/r/tealmac/birth-date-field
- Screenshot: https://shadcn.exchange/shot/tealmac/birth-date-field/light.png
- Registry item: https://ui.tealmac.com/r/birth-date-field.json
- Listed: 2026-11-01, source last changed 2026-11-01

## Install

```bash
npx shadcn@latest add https://shadcn.exchange/r/tealmac/birth-date-field.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@tealmac/date-field`, `@tealmac/date-time-core`

## Files

### `registry/patterns/birth-date-field/birth-date-field.tsx`

```tsx
"use client"

import * as React from "react"

import { DateField } from "@/components/ui/date-field"
import { ageOn, today as todayISO } from "@/components/ui/date-time-core"

export interface BirthDateFieldProps {
  value?: string | null
  defaultValue?: string | null
  onValueChange?: (value: string | null) => void
  maxAge?: number
  today?: string
  name?: string
  locale?: string
}

export function validateBirthDate(
  date: string | null,
  today: string,
  maxAge = 120
) {
  if (!date) return { age: null, error: null }
  if (date > today)
    return { age: null, error: "A date of birth cannot be in the future." }
  const age = ageOn(date, today)
  if (age > maxAge)
    return { age, error: `Check the year: that would make you ${age}.` }
  return { age, error: null }
}

export function BirthDateField({
  value,
  defaultValue = null,
  onValueChange,
  maxAge = 120,
  today,
  name,
  locale,
}: BirthDateFieldProps) {
  const now = today ?? todayISO()
  const [inner, setInner] = React.useState<string | null>(defaultValue)
  const date = value === undefined ? inner : value
  const { age, error } = validateBirthDate(date, now, maxAge)
  const id = React.useId()

  return (
    <div className="flex flex-col gap-1.5">
      <DateField
        label="Date of birth"
        locale={locale}
        name={name}
        value={date}
        aria-describedby={id}
        invalid={!!error}
        onValueChange={(next) => {
          if (value === undefined) setInner(next)
          onValueChange?.(next)
        }}
      />
      <p
        id={id}
        role={error ? "alert" : "status"}
        className={
          error ? "text-destructive text-sm" : "text-muted-foreground text-sm"
        }
      >
        {error ??
          (age !== null
            ? `You are ${age} year${age === 1 ? "" : "s"} old.`
            : "")}
      </p>
    </div>
  )
}
```
