# Date range picker

> Pick a start and an end on a calendar that previews the range as you move.

Component · Pro · https://lodeui.com/components/date-range-picker

## When to use

- Filtering reports, logs or bookings by a span of days.
- Choosing travel or booking dates with presets for common ranges.

## When not to use

- A single date: use a date picker.
- Fuzzy ranges like 'last 30 days' only: use a segmented control.

## Installation

```bash
npx shadcn@latest add @lode/date-range-picker
```

Pro: needs a Lode API key and the `@lode` registry in components.json. See https://lodeui.com/docs/cli.

npm dependencies: motion, lucide-react

## Usage

```tsx title="example.tsx"
import * as React from "react";
import { DateRangePicker, countDays, type DateRange } from "@/components/ui/date-range-picker";

export function ReportRange() {
  const [range, setRange] = React.useState<DateRange>({ from: new Date(2026, 9, 1), to: new Date(2026, 9, 7) });
  return (
    <div className="flex items-center gap-3">
      <DateRangePicker value={range} onValueChange={setRange} />
      <span className="text-sm text-muted-foreground">{countDays(range)} days</span>
    </div>
  );
}
```

## API reference

### DateRangePicker

A trigger showing the formatted range and a calendar popover. The first click sets the start, the second the end.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| value / defaultValue | `{ from: Date; to: Date }` | – | Controlled or uncontrolled range. |
| onValueChange | `(range: DateRange) => void` | – | Called once both ends are picked, or a preset is chosen. |
| presets | `{ label: string; range: DateRange }[]` | – | Shortcuts shown beside the calendar from 640px up. |
| align | `"start" \| "center" \| "end"` | `"center"` | Popover alignment. |

### countDays

Inclusive number of days in a range, safe across daylight-saving changes.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| range | `DateRange` | – | The range to count. |

### formatRange

Compact label like 'Oct 1 – 7, 2026'. Locale-independent, so server and client agree.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| range | `DateRange` | – | The range to format. |

## Keyboard interactions

| Keys | Action |
| --- | --- |
| ← / → | Previous or next day |
| ↑ / ↓ | Previous or next week |
| Enter / Space | Pick the focused day |
| Esc | Close |

## Accessibility

- Each day is a labelled button (e.g. 'October 10, 2026') inside a role="grid".
- The month heading is a polite live region, so paging is announced.
- Selected days are marked with aria-pressed.

## Motion

- Months slide in the direction you page.
- While picking the end, the range band previews under the pointer.

## Responsive behavior

- The calendar is 280px wide; presets hide below 640px to fit phones.
- The popover centers under the trigger by default.

## Performance

- The grid is 42 buttons computed from plain Date math; no date library.

## Notes for AI

- Dates are local calendar dates; convert to UTC at your API boundary.
- Use formatRange for labels to avoid hydration mismatches from toLocaleDateString.

## Related

- [Select](https://lodeui.com/components/select) — A pill trigger with a springy menu, typeahead, and full keyboard support.
- [Popover](https://lodeui.com/components/popover) — An anchored panel for filters, forms and details.
- [Segmented control](https://lodeui.com/components/segmented-control) — A compact single choice with a pill that slides to the selection.
