# Date picker

> One date, typed or picked: the field reads "tomorrow", "next fri" or "4 nov", and the calendar slides by month while one mark glides between days.

Date fields usually make you click through a calendar or type an exact format. This one reads what people write ("tomorrow", "in 3 days", "next fri", "4 nov", "2026-11-04") and settles it into "Wed 4 Nov 2026"; anything it can't read shakes and says so. The calendar rises off the field, months slide in from the side you moved toward while the month name morphs, and the chosen day's mark glides from day to day. Values are plain "YYYY-MM-DD" strings, so time zones never shift a day.

## Install

```bash
npx shadcn@latest add https://hairlineui.com/r/date-picker.json
```

Needs React 19, Tailwind CSS v4 and shadcn/ui theme variables (any style, light and dark). Icons from lucide-react.

- npm: none
- Hairline UI components it needs (the CLI installs them too): `text-morph`, `ui-interaction-motion`
- Docs and live preview: https://hairlineui.com/ui/date-picker
- Registry item (source): https://hairlineui.com/r/date-picker.json

## Usage

```tsx
import { DatePicker } from "@/components/ui/date-picker";

<DatePicker label="Due" value={due} onValueChange={setDue} min="2026-10-20" />
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `value / defaultValue` | `string \| null` | – | "YYYY-MM-DD". |
| `onValueChange` | `(value: string \| null) => void` | – | Called with the new day (null when cleared). |
| `min / max` | `string` | – | Allowed range. |
| `weekStartsOn` | `0 \| 1` | `1` | Sunday or Monday. |
| `locale` | `string` | `"en-GB"` | Formatting. |
| `label / hint / error / placeholder` | `ReactNode` | – | As in Input. |

## States

- **typed**: Enter or leaving the field settles the text into a formatted date.
- **unreadable**: Red line, a hint of what works, one shake.
- **calendar**: Rises off the field; months slide 24px out of a blur (360ms); the month name morphs.
- **pick**: The mark glides to the day; the calendar closes and focus returns to the field.

## What it handles

Calendars are slow for dates people already know, and typed fields are strict about format. This accepts both.

- **Natural typing**: today, tomorrow, weekdays, "in 3 days/weeks/months", "4 nov", "nov 4", 4/11/2026, ISO.
- **Moving mark**: One selection circle thrown between days (420ms).
- **Full keyboard**: Arrows by day/week, Page Up/Down by month, Home/End, Enter.
- **No time-zone bugs**: Plain YYYY-MM-DD strings in and out.

## Replaces

react-day-picker, date-fns parsing, native <input type="date">

## Where it fits

- **Due dates**: Set a task for "next fri" without opening anything.
- **Bookings**: A delivery or appointment day with limits.
- **Filters**: A single "since" date above a report.
- **Profiles**: Start dates and birthdays.

## Notes

- parseDate(input, today) is exported for your own fields.
- Alt+↓ opens the calendar from the field; the grid uses role="grid" with labelled days.
- Reduced motion: months and the mark change in place.

License: MIT (https://hairlineui.com/license#components)
