# Date picker

A button that opens a calendar in a popover and shows the chosen day. Nothing is chosen until the person picks; the button then reads the exact date in the locale ("8 Nov 2026"). Shortcuts like "Tomorrow" are allowed, but each prints the exact date beside its words and the button only ever shows the date, never the phrase. Escape closes the popover and focus returns to the button.

- Registry name: `date-picker` (`@candor/date-picker`)
- Tier: Pro. Installing it needs a Pro, Premium or Team licence key: the person runs `npx candor-ui key <key>` themselves; never ask for the key in chat or write it to a file.
- Docs: https://candor.themethodic.com/docs/date-picker

## Install

```bash
npx candor-ui add date-picker
```

Run `npx candor-ui@latest init` once first (https://candor.themethodic.com/get-started.md). Without the CLI: `npx shadcn@latest add @candor/date-picker`.
It brings in: button, calendar, locale, locked, popover, tokens, utils.
npm packages: lucide-react@^1.67.0.

## Example

```tsx
"use client"

import * as React from "react"
import { DatePicker } from "@/components/candor/ui/date-picker"

// "Tomorrow" is a phrase; the picker prints the exact date beside it, and the button only ever shows the date.
const today = new Date(2026, 10, 8)
const at = (days: number) => new Date(2026, 10, 8 + days)

export default function Example() {
  const [due, setDue] = React.useState<Date | undefined>()
  return (
    <div className="flex flex-col items-start gap-2">
      <label htmlFor="due" className="text-sm font-medium">
        Due date
      </label>
      <DatePicker
        id="due"
        value={due ?? null}
        onValueChange={setDue}
        today={today}
        defaultMonth={today}
        clearable
        presets={[
          { label: "Tomorrow", date: at(1) },
          { label: "In a week", date: at(7) },
          { label: "In a month", date: new Date(2026, 11, 8) },
        ]}
      />
    </div>
  )
}
```

## <DatePicker>

Props:

- `value?: Date | null | undefined`: The chosen day, when you control it. `null` is nothing chosen.
- `defaultValue?: Date | undefined`: The day chosen at first, when you don't control it. Left out, nothing is chosen.
- `onValueChange?: ((date: Date | undefined) => void) | undefined`: Called with the day a person picks, or `undefined` when they clear it.
- `presets?: DatePreset[] | undefined`: Shortcuts shown beside the calendar, each with its exact date.
- `unavailable?: ((date: Date) => string | null | undefined | false) | undefined`: Returns why a day can't be picked, or nothing when it can; passed to the calendar. Needs a `TooltipProvider`.
- `clearable?: boolean | undefined` (default `false`): Shows a "Clear date" button once a day is chosen.
- `locked?: string | null | undefined`: Why the picker can't be used right now. The button stays focusable and says why. Needs a `TooltipProvider`.
- `placeholder?: string | undefined`: Text on the button while nothing is chosen. Defaults to "Pick a date".
- `defaultMonth?: Date | undefined`: The month the calendar opens on when nothing is chosen. Defaults to today's.
- `today?: Date | undefined`: The day to outline as today in the calendar.
- `id?: string | undefined`
- `className?: string | undefined`
- `"aria-label"?: string | undefined`: The button's accessible name when it needs one beyond its text (the field's label).

## Strings (`datePicker`)

The fixed words, English by default. Override any of them under `datePicker` in `<LocaleProvider strings={{ datePicker: { … } }}>`; the table is exported as `datePickerStrings`.

- `placeholder`: Pick a date
- `presets`: Shortcuts
- `clear`: Clear date

## Types

### DatePreset

A shortcut such as "Tomorrow" or "In 7 days". The exact date is always printed beside the words.

```ts
{
  /** The relative phrase: "Tomorrow", "Next Monday". */
  label: string;
  /** The day it means, worked out by the app. Shown beside the label so nobody has to guess what "next week" is. */
  date: Date;
}
```

## Motion

- **tint** (tint): A shortcut's background changes when the pointer is over it, and a ring fades in when it takes keyboard focus.

Set with `--cd-motion-date-picker-<moment>-*` in your brand file; the families are in the design reference.

## Rules for using Candor UI

- Components take plain typed data. Never pass model output as HTML or render it as a link; messages are typed blocks.
- A control that can't be used says why: wrap it in `<Locked reason="…">`, don't just disable it.
- Don't show a value you don't have: leave it out (it renders as —) rather than guess. An estimate is labelled as one.
- Nothing is pre-selected in a decision a person makes, and the agent is named from your app's data, never from model output.
- Your app's words go in `LocaleProvider`: its fixed strings in `strings`, its nouns in `nouns`; entity kinds and agent roles in `EntityKindsProvider` and `AgentRolesProvider`.
