February 2026

Selected: None

const [date, setDate] = useState<Date>();
<DatePicker mode="single" selected={date} onChange={setDate} />

Installation

Barrel

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

Granular

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

Usage

DatePicker supports three selection modes: single, multiple, and range.

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}
    />
  );
}

Examples

Single Date Selection

Select a single date. The most common use case for date pickers.

February 2026

Selected: None

const [date, setDate] = useState<Date>();

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

Multiple Date Selection

Select multiple individual dates. Use max to limit the number of selections.

February 2026

Selected: 0 date(s)

const [dates, setDates] = useState<Date[]>();

<DatePicker
  mode="multiple"
  selected={dates}
  onChange={setDates}
  max={5}
/>

Date Range Selection

Select a continuous range of dates. Works well with numberOfMonths=2 for a side-by-side view.

February 2026
March 2026

Range: None

const [range, setRange] = useState<DateRange>();

<DatePicker
  mode="range"
  selected={range}
  onChange={setRange}
  numberOfMonths={2}
/>

Range with Min/Max Constraints

Constrain the range length using min and max props (in days/nights).

February 2026
<DatePicker
  mode="range"
  selected={range}
  onChange={setRange}
  min={3}
  max={7}
  footer={<span>Select 3-7 nights</span>}
/>

With Popover

Compose with the Popover component to create a dropdown date picker.

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

Date Range with Popover

A date range picker in a popover with two months displayed.

<Popover>
  <Popover.Trigger asChild>
    <Button variant="outline" icon={CalendarDotsIcon}>
      {formatRange()}
    </Button>
  </Popover.Trigger>
  <Popover.Content className="p-1">
    <DatePicker
      mode="range"
      selected={range}
      onChange={(r) => setRange(r)}
      numberOfMonths={2}
    />
  </Popover.Content>
</Popover>

Date Range with Presets

Combine the date picker with preset options for quick selection.

<Popover>
  <Popover.Trigger asChild>
    <Button variant="outline" icon={CalendarDotsIcon}>
      {formatRange()}
    </Button>
  </Popover.Trigger>
  <Popover.Content className="p-0">
    <div className="flex">
      <div className="flex flex-col gap-1 border-r border-kumo-line p-2 text-sm">
        {presets.map((preset) => (
          <button
            key={preset.label}
            onClick={() => setRange(preset.range)}
            className="rounded-md px-3 py-1.5 text-left hover:bg-kumo-control"
          >
            {preset.label}
          </button>
        ))}
      </div>
      <div className="p-1">
        <DatePicker
          mode="range"
          selected={range}
          onChange={(r) => setRange(r)}
          numberOfMonths={2}
        />
      </div>
    </div>
  </Popover.Content>
</Popover>

Disabled Dates with Usage Limits

Use the disabled prop to make certain dates unselectable, and footer to display usage information.

February 2026
const unavailableDates = [
  new Date(2025, 0, 5),
  new Date(2025, 0, 12),
];

<DatePicker
  mode="multiple"
  selected={dates}
  onChange={setDates}
  max={5}
  disabled={unavailableDates}
  footer={
    <p className="text-xs text-kumo-subtle pt-2">
      {selectedCount}/{maxDays} days selected. Grayed dates are unavailable.
    </p>
  }
/>

Full Popover Example

Here's a complete example showing how to compose DatePicker with Popover:

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>
  );
}

API Reference

DatePicker forwards all props to react-day-picker. Key props include:

  • mode"single" | "multiple" | "range" — Selection mode (required)
  • selected — Currently selected date(s)
  • onChange — Callback when selection changes
  • numberOfMonths — Number of months to display
  • disabled — Dates that cannot be selected
  • min / max — Min/max selection constraints
  • footer — Content rendered below the calendar
  • locale — date-fns locale for internationalization
  • className — Additional CSS classes

See the react-day-picker documentation for the full API.

Differences from react-day-picker

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.