Form

Date Range Picker

A start/end date field with quick presets. Two months side by side on wide screens, one under 640px; the range previews as you hover or move with the keyboard.

Usage

  • Use for report periods, filters and bookings.
  • Offer presets for the common ranges; most people never open the grid.
  • Don’t use two DatePickers for a period; the range preview prevents end-before-start mistakes.

Installation

Install the package (React 19):

terminal
npm install @krackedui/motion

Import the styles once, in your app entry or root layout:

/src/main.tsx
import '@krackedui/motion/styles.css';

Use it anywhere inside your app's <Theme> (see Installation):

/src/DateRangePickerExample.tsx
import { useState } from 'react';
import { DateRangePicker, Select, type DateRange } from '@krackedui/motion';

const today = new Date();
const daysAgo = (n: number) => new Date(today.getFullYear(), today.getMonth(), today.getDate() - n);
const presets = [
  { label: 'Today', range: { from: daysAgo(0), to: daysAgo(0) } },
  { label: 'Last 7 days', range: { from: daysAgo(6), to: daysAgo(0) } },
  { label: 'Last 30 days', range: { from: daysAgo(29), to: daysAgo(0) } },
];

export function InvoiceFilters() {
  const [range, setRange] = useState<DateRange>(presets[1].range);
  const [status, setStatus] = useState('all');
  return (
    <div className="flex flex-wrap items-end gap-2">
      <DateRangePicker aria-label="Period" className="w-full sm:w-72" value={range} onValueChange={setRange} presets={presets} />
      <Select
        aria-label="Status"
        className="w-full sm:w-36"
        value={status}
        onValueChange={setStatus}
        options={[{ value: 'all', label: 'All statuses' }, { value: 'paid', label: 'Paid' }, { value: 'due', label: 'Due' }]}
      />
    </div>
  );
}

Examples

In a Field, with min

Check-in from today.

Invalid and disabled

Choose a period of 90 days or less.

Dark theme

API Reference

DateRangePicker

The ref goes to the trigger <button>.

PropTypeDefault
value / defaultValue
DateRange
{ from: null, to: null }
onValueChange
(value: DateRange) => void
placeholder
string
"Pick a date range"
min / max
Date
presets
{ label: string; range: DateRange }[]
size
"sm""md""lg"
"md"
clearable
boolean
true
locale
string
"en-US"
weekStartsOn
01
0
today
Date
new Date()
open
boolean
defaultOpen
boolean
onOpenChange
(open: boolean) => void
invalid
boolean
false
disabled
boolean
false
required
boolean
false
name
string
id
string
className
string
style
CSSProperties
aria-label
string
aria-describedby
string

Accessibility

  • The trigger is a button with aria-haspopup="dialog"; the popover is a dialog named "Choose dates".
  • Each month is a date grid with the Calendar keys; moving past the last visible month scrolls the months.
  • First Enter / click sets the start, the second sets the end (in either order) and closes; a polite status line says "Pick an end date" in between.
  • Presets are toggle buttons (aria-pressed for the active one).
© 2026 Motion. Internal documentation.