---
layout: ~/layouts/MdxDocLayout.astro
title: "DatePicker"
description: "A date selection calendar supporting single, multiple, and range selection modes."
sourceFile: "components/date-picker"
---

import ComponentExample from "~/components/docs/ComponentExample.astro";
import ComponentSection from "~/components/docs/ComponentSection.astro";
import PropsTable from "~/components/docs/PropsTable.astro";
import {
  DatePickerSingleDemo,
  DatePickerMultipleDemo,
  DatePickerRangeDemo,
  DatePickerRangeMinMaxDemo,
  DatePickerPopoverDemo,
  DatePickerRangePopoverDemo,
  DatePickerRangeWithPresetsDemo,
  DatePickerDisabledWithFooterDemo,
} from "~/components/demos/DatePickerDemo";

{/* Hero Demo */}

<ComponentSection>
  <ComponentExample demo="DatePickerSingleDemo">
    <DatePickerSingleDemo client:load />
  </ComponentExample>
</ComponentSection>

{/* Installation */}

<ComponentSection>

## Installation

### Barrel

```tsx
import { DatePicker, type DateRange } from "@cloudflare/kumo";
```

### Granular

```tsx
import {
  DatePicker,
  type DateRange,
} from "@cloudflare/kumo/components/date-picker";
```

</ComponentSection>

{/* Usage */}

<ComponentSection>

## Usage

<p>
  DatePicker supports three selection modes: `single`, `multiple`, and `range`.
</p>

```tsx
import { useState } from "react";
import { DatePicker } from "@cloudflare/kumo";

export default function Example() {
  const [date, setDate] = useState<Date>();

  return <DatePicker mode="single" selected={date} onChange={setDate} />;
}
```

</ComponentSection>

{/* Examples */}

<ComponentSection>

## Examples

### Single Date Selection

<p>Select a single date. The most common use case for date pickers.</p>
<ComponentExample demo="DatePickerSingleDemo">
  <DatePickerSingleDemo client:load />
</ComponentExample>

### Multiple Date Selection

<p>
  Select multiple individual dates. Use `max` to limit the number of selections.
</p>
<ComponentExample demo="DatePickerMultipleDemo">
  <DatePickerMultipleDemo client:load />
</ComponentExample>

### Date Range Selection

<p>
  Select a continuous range of dates. Works well with `numberOfMonths={2}` for a
  side-by-side view.
</p>
<ComponentExample demo="DatePickerRangeDemo">
  <DatePickerRangeDemo client:load />
</ComponentExample>

### Range with Min/Max Constraints

<p>Constrain the range length using `min` and `max` props (in days/nights).</p>
<ComponentExample demo="DatePickerRangeMinMaxDemo">
  <DatePickerRangeMinMaxDemo client:load />
</ComponentExample>

### With Popover

<p>
  Compose with the [Popover](/components/popover) component to create a dropdown
  date picker.
</p>
<ComponentExample demo="DatePickerPopoverDemo">
  <DatePickerPopoverDemo client:load />
</ComponentExample>

### Date Range with Popover

<p>A date range picker in a popover with two months displayed.</p>
<ComponentExample demo="DatePickerRangePopoverDemo">
  <DatePickerRangePopoverDemo client:load />
</ComponentExample>

### Date Range with Presets

<p>Combine the date picker with preset options for quick selection.</p>
<ComponentExample demo="DatePickerRangeWithPresetsDemo">
  <DatePickerRangeWithPresetsDemo client:load />
</ComponentExample>

### Disabled Dates with Usage Limits

  <p>
    Use the `disabled` prop to make certain dates unselectable,
    and `footer` to display usage information.
  </p>
  <ComponentExample demo="DatePickerDisabledWithFooterDemo">
    <DatePickerDisabledWithFooterDemo client:load />
  </ComponentExample>
</ComponentSection>

{/* Full Popover Example */}

<ComponentSection>

## Full Popover Example

<p>Here's a complete example showing how to compose DatePicker with Popover:</p>

```tsx
import { useState } from "react";
import { DatePicker, Popover, Button } from "@cloudflare/kumo";
import { CalendarDotsIcon } from "@phosphor-icons/react";

export function DatePickerDropdown() {
  const [date, setDate] = useState<Date>();

  return (
    <Popover>
      <Popover.Trigger
        render={<Button variant="outline" icon={CalendarDotsIcon} />}
      >
        {date ? date.toLocaleDateString() : "Pick a date"}
      </Popover.Trigger>
      <Popover.Content className="p-3">
        <DatePicker
          mode="single"
          selected={date}
          onChange={(d) => setDate(d)}
        />
      </Popover.Content>
    </Popover>
  );
}
```

</ComponentSection>

{/* API Reference */}

<ComponentSection>

## API Reference

<p>
  DatePicker forwards all props to
  <a
    href="https://daypicker.dev/api/interfaces/PropsBase"
    target="_blank"
    rel="noopener noreferrer"
  >
    react-day-picker
  </a>
  . Key props include:
</p>
<ul class="mt-4 list-disc list-inside space-y-2">
  <li>
    `mode` — `"single" | "multiple" | "range"` — Selection mode (required)
  </li>
  <li>`selected` — Currently selected date(s)</li>
  <li>`onChange` — Callback when selection changes</li>
  <li>`numberOfMonths` — Number of months to display</li>
  <li>`disabled` — Dates that cannot be selected</li>
  <li>`min` / `max` — Min/max selection constraints</li>
  <li>`footer` — Content rendered below the calendar</li>
  <li>`locale` — date-fns locale for internationalization</li>
  <li>`className` — Additional CSS classes</li>
</ul>
<p class="mt-4 text-kumo-subtle text-sm">
  See the
  <a
    href="https://daypicker.dev/docs"
    target="_blank"
    rel="noopener noreferrer"
  >
    react-day-picker documentation
  </a>
  for the full API.
</p>

### Differences from react-day-picker

  <p>
    For consistency with other Kumo form components, DatePicker uses `onChange` instead of react-day-picker's `onSelect`.
    Full type inference is preserved — TypeScript will correctly narrow the callback signature based on the `mode` prop.
  </p>
</ComponentSection>
