March 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.

March 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.

March 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.

March 2026
April 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).

March 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.

March 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.