---
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 Heading from "~/components/docs/Heading.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>
  <Heading level={2}>Installation</Heading>
  <Heading level={3}>Barrel</Heading>

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

<Heading level={3}>Granular</Heading>

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

</ComponentSection>

{/* Usage */}

<ComponentSection>
  <Heading level={2}>Usage</Heading>
  <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>
  <Heading level={2}>Examples</Heading>

<Heading level={3}>Single Date Selection</Heading>
<p>Select a single date. The most common use case for date pickers.</p>
<ComponentExample demo="DatePickerSingleDemo">
  <DatePickerSingleDemo client:load />
</ComponentExample>

<Heading level={3}>Multiple Date Selection</Heading>
<p>
  Select multiple individual dates. Use `max` to limit the number of selections.
</p>
<ComponentExample demo="DatePickerMultipleDemo">
  <DatePickerMultipleDemo client:load />
</ComponentExample>

<Heading level={3}>Date Range Selection</Heading>
<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>

<Heading level={3}>Range with Min/Max Constraints</Heading>
<p>Constrain the range length using `min` and `max` props (in days/nights).</p>
<ComponentExample demo="DatePickerRangeMinMaxDemo">
  <DatePickerRangeMinMaxDemo client:load />
</ComponentExample>

<Heading level={3}>With Popover</Heading>
<p>
  Compose with the
  <a href="/components/popover" class="text-kumo-link hover:underline">
    Popover
  </a>
  component to create a dropdown date picker.
</p>
<ComponentExample demo="DatePickerPopoverDemo">
  <DatePickerPopoverDemo client:load />
</ComponentExample>

<Heading level={3}>Date Range with Popover</Heading>
<p>A date range picker in a popover with two months displayed.</p>
<ComponentExample demo="DatePickerRangePopoverDemo">
  <DatePickerRangePopoverDemo client:load />
</ComponentExample>

<Heading level={3}>Date Range with Presets</Heading>
<p>Combine the date picker with preset options for quick selection.</p>
<ComponentExample demo="DatePickerRangeWithPresetsDemo">
  <DatePickerRangeWithPresetsDemo client:load />
</ComponentExample>

  <Heading level={3}>Disabled Dates with Usage Limits</Heading>
  <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>
  <Heading level={2}>Full Popover Example</Heading>
  <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 asChild>
        <Button variant="outline" icon={CalendarDotsIcon}>
          {date ? date.toLocaleDateString() : "Pick a date"}
        </Button>
      </Popover.Trigger>
      <Popover.Content className="p-3">
        <DatePicker
          mode="single"
          selected={date}
          onChange={(d) => setDate(d)}
        />
      </Popover.Content>
    </Popover>
  );
}
```

</ComponentSection>

{/* API Reference */}

<ComponentSection>
  <Heading level={2}>API Reference</Heading>
  <p>
    DatePicker forwards all props to <a href="https://daypicker.dev/api/interfaces/PropsBase" class="text-kumo-link hover:underline" target="_blank" rel="noopener noreferrer">react-day-picker</a>. 
    Key props include:
  </p>
  <ul class="mt-4 list-disc list-inside text-kumo-strong space-y-2">
    <li>`mode` — <code class="text-xs">"single" | "multiple" | "range"</code> — 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" class="text-kumo-link hover:underline" target="_blank" rel="noopener noreferrer">react-day-picker documentation</a> for the full API.
  </p>

  <Heading level={3}>Differences from react-day-picker</Heading>
  <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>
