# Date Picker

> A field that shows a day, like "Sat 3 Oct", and opens a calendar under it to pick one. Weeks start on Monday, and the year shows only when it is not this year.

- Name: `date-picker`
- Status: beta
- Categories: dates, forms
- File: the install writes `date-picker.tsx` to your `ui` alias, `@/components/ui` by default.
- Other registry items: `@txbrendan/calendar`, `@txbrendan/field-frame`, `@txbrendan/popover`. The install adds them.
- Gallery: https://txbrendan.dev/components/date-picker
- Registry item: https://txbrendan.dev/r/date-picker.json

## Install

1. Add the registry to `components.json`. Do this first, once:

   ```bash
   npx shadcn@latest registry add "@txbrendan=https://txbrendan.dev/r/{name}.json"
   ```

   The command writes this entry. You can also add it by hand:

   ```json
   {
     "registries": {
       "@txbrendan": "https://txbrendan.dev/r/{name}.json"
     }
   }
   ```

   Without this step, the shadcn CLI looks up `@txbrendan` in a public list that txbrendan/ui does not control.

2. Add the theme once per app. It replaces your color tokens with ones checked for contrast:

   ```bash
   npx shadcn@latest add @txbrendan/theme
   ```

3. Add the component:

   ```bash
   npx shadcn@latest add @txbrendan/date-picker
   ```

## Use it for

- One day for something people plan: a meeting, a workshop, an invoice's due date.
- Give it a label, like "Event date". Without one, pass aria-label.
- The value is a day as "YYYY-MM-DD", with no time and no time zone.
- Set min and max for the days people may pick, and disabledDates for days that are taken.
- Put what is wrong in error, like "Pick a day from today on." It replaces the hint and is said once.
- Pass name to send the day with a form.

## Avoid it for

- A start and an end day. Use a Calendar with mode="range".
- A calendar that stays on the page, like a schedule. Use a Calendar.
- A birth date or another day far in the past. Typing it is quicker than paging back through months.

## Props

- `label`: `ReactNode`. Names the field, above it. Pressing it focuses the button and does not open the calendar.
- `value`: `string | null`. The picked day, "YYYY-MM-DD". Use it with onValueChange.
- `defaultValue`: `string | null`. The picked day at first render, when you do not control it.
- `onValueChange`: `(day: string) => void`. Called with the new day when someone picks one.
- `placeholder`: `string`. Default `"Pick a date"`. Shown while no day is picked.
- `hint`: `ReactNode`. A short note under the field.
- `error`: `ReactNode`. Replaces the hint, in red, and is announced once.
- `min`: `string`. The earliest day people can pick, "YYYY-MM-DD".
- `max`: `string`. The latest day people can pick, "YYYY-MM-DD".
- `disabledDates`: `string[] | (date: string) => boolean`. Days people cannot pick.
- `weekStartsOn`: `0 | 1 | 2 | 3 | 4 | 5 | 6`. Default `1`. The first column. 1 is Monday.
- `locale`: `string`. Default `"en-GB"`. A language tag for the button and the calendar.
- `size`: `"sm" | "md" | "lg"`. Default `"md"`. Height and text size of the button, the label, and the calendar.
- `disabled`: `boolean`. Default `false`. Blocks the button.
- `name`: `string`. Form field name. Sends the day, or nothing while none is picked.
- `aria-label`: `string`. Names the field when there is no visible label.
- `className`: `string`. Classes for the frame. Later classes win.

## Accessibility

- The button's name is the label and then the day, like "Event date, Sat 3 Oct". It says it opens a dialog, and whether it is open.
- The calendar opens with focus on the picked day, or today, or the month's first day.
- In the calendar the arrows move a day or a week, Home and End go to the week's ends, and Page Up and Page Down move a month, with Shift a year.
- Enter, Space, or a click picks a day. That closes the calendar and puts focus back on the button.
- Escape or a click outside closes it without a change.
- The hint or the error describes the button. The error is announced once when it appears.

## Examples

### With a picked day and a hint

```tsx
<DatePicker label="Event date" defaultValue="2026-10-03" hint="It starts at 10:00." />
```

### Limits and taken days

```tsx
<DatePicker
  label="Friendly"
  min="2026-10-26"
  max="2026-12-20"
  disabledDates={["2026-10-31", "2026-11-07"]}
/>
```
