Range Picker

A date/time range picker built on the Temporal API. Supports date-only and date+time modes, timezone awareness, keyboard input, and flexible popup placement.

Installation

npm install @dayflow/ui-range-picker

For projects that already use Tailwind CSS, import the component-only bundle:

@import '@dayflow/ui-range-picker/dist/styles.components.css';
@import 'tailwindcss';

For projects that do not use Tailwind CSS, import the full stylesheet instead:

import { RangePicker } from '@dayflow/ui-range-picker';
import '@dayflow/ui-range-picker/dist/styles.css';

Basic Usage

import { useState } from 'react';
import { Temporal } from 'temporal-polyfill';
import { RangePicker } from '@dayflow/ui-range-picker';
import type { ZonedRange } from '@dayflow/ui-range-picker';

function MyComponent() {
  const [range, setRange] = useState<ZonedRange>([
    Temporal.Now.zonedDateTimeISO(),
    Temporal.Now.zonedDateTimeISO().add({ hours: 1 }),
  ]);

  return <RangePicker value={range} onChange={value => setRange(value)} />;
}

Date-Only Mode

Pass showTime={false} to hide the time selector.

<RangePicker
  value={range}
  showTime={false}
  format='YYYY-MM-DD'
  onChange={value => setRange(value)}
/>

With Timezone

<RangePicker
  value={range}
  timeZone='America/New_York'
  onChange={(value, dateStrings) => {
    console.log('range:', value);
    console.log('formatted:', dateStrings); // ['2024-10-15 10:00', '2024-10-15 11:00']
  }}
/>

Custom Time Format

<RangePicker
  value={range}
  format='MM/DD/YYYY'
  showTime={{ format: 'hh:mm A' }}
  onChange={value => setRange(value)}
  onOk={value => saveToBackend(value)}
/>

The popup defaults to bottomLeft and automatically adjusts to avoid viewport overflow.

<RangePicker
  value={range}
  placement='topRight'
  autoAdjustOverflow={true}
  onChange={value => setRange(value)}
/>

Locale

Pass a BCP 47 locale string to localize month names and weekday labels.

<RangePicker value={range} locale='zh-CN' onChange={value => setRange(value)} />

To translate the picker's own labels (navigation buttons, start/end inputs, hour/minute lists and the OK button), pass a locale object with messages. Missing keys fall back to English. The calendar's built-in event panel and dialog fill these in from the calendar locale automatically.

<RangePicker
  value={range}
  locale={{
    code: 'fr-FR',
    messages: {
      previousYear: 'Année précédente',
      previousMonth: 'Mois précédent',
      nextMonth: 'Mois suivant',
      nextYear: 'Année suivante',
      startDate: 'Date de début',
      endDate: 'Date de fin',
      hour: 'Heure',
      minute: 'Minute',
      ok: 'OK',
    },
  }}
  onChange={value => setRange(value)}
/>

Set calendarSystem='jalali' to display and type dates in the Persian calendar. onChange and onOk still return ISO Temporal values.

Match Trigger Width

<RangePicker
  value={range}
  matchTriggerWidth
  onChange={value => setRange(value)}
/>

API Reference

RangePicker

PropTypeDefaultDescription
value[Temporal.PlainDate | PlainDateTime | ZonedDateTime, ...]—Controlled range value. Accepts any mix of Temporal types.
formatstring"YYYY-MM-DD"Display and parse format for date part
showTimeboolean | { format?: string }trueEnable time selection. Pass an object to set a custom time format.
showTimeFormatstring"HH:mm"Default time format when showTime is true
onChange(value: ZonedRange, dateString: [string, string]) => void—Fires on every selection change
onOk(value: ZonedRange, dateString: [string, string]) => void—Fires when the user confirms the selection with the OK button
timeZonestring—IANA timezone string (e.g. "America/New_York"). Defaults to system zone.
disabledbooleanfalseDisables all interactions
placement'bottomLeft' | 'bottomRight' | 'topLeft' | 'topRight''bottomLeft'Preferred popup position
autoAdjustOverflowbooleantrueFlip placement automatically when the popup would overflow the viewport
getPopupContainer() => HTMLElement—Mount the popup inside a custom container instead of document.body
matchTriggerWidthbooleanfalseSet the popup width to match the trigger input width
localestring | { code: string; messages?: Record<string, string> }'en-US'BCP 47 locale code; an object's messages translate the picker labels
calendarSystem'gregorian' | 'jalali''gregorian'Calendar used to display and parse dates

ZonedRange

type ZonedRange = [Temporal.ZonedDateTime, Temporal.ZonedDateTime];

The onChange and onOk callbacks always receive a ZonedRange regardless of the input value type, normalized to the active timezone.

On this page