Marble UI
← Components

Date Range Picker

Preview: Range

Date (or range) field with a calendar popover; segments are editable by keyboard.

Import

import { DatePicker, DateRangePicker } from '@marbleui/ui'

This is a style of date-picker; see its examples for all variants.

Props

<DatePicker>

PropTypeDefaultDescription
descriptionReactNode—
errorMessagestring | ((validation: ValidationResult) => string)—
labelReactNode—
variantFieldVariant—

Also accepts React Aria props (112).

<DateRangePicker>

PropTypeDefaultDescription
descriptionReactNode—
errorMessagestring | ((validation: ValidationResult) => string)—
labelReactNode—
months1 | 22
variantFieldVariant—

Also accepts React Aria props (113).

Accessibility

Keyboard interaction, focus management and ARIA semantics come from the underlying primitives: React Aria Button · React Aria DateInput · React Aria DatePicker · React Aria DateRangePicker · React Aria DateSegment · React Aria Dialog · React Aria Group. Follow the primitive's docs for the full keyboard map.

Usage notes

DateRangePicker is a start and an end date field under one label, with a two-month RangeCalendar in its popover. Use it for reporting periods, bookings and filters; for a range that stays on screen, use RangeCalendar.

import { today, getLocalTimeZone } from '@internationalized/date'
const t = today(getLocalTimeZone())
<DateRangePicker
  label="Reporting period"
  defaultValue={{ start: t.subtract({ days: 30 }), end: t }}
  maxValue={t}
  startName="from"
  endName="to"
/>
  • The value is { start, end }, or null when empty. Controlled: value + onChange. In a form, startName and endName submit the two dates as separate fields.
  • months sets how many months the popover shows: 2 by default, months={1} for narrow layouts.
  • Screen readers hear the two inputs as “Start Date” and “End Date” under your label. An end typed before the start makes the field invalid with “Start date must be before end date.”
  • With isDateUnavailable, a range can’t cross an unavailable day unless allowsNonContiguousRanges is set.
Example source · show
import { getLocalTimeZone, now, today } from '@internationalized/date'
import { DatePicker, DateRangePicker } from './date-picker'

export const styles = {
  Date: () => <DatePicker className="w-60" label="Due date" defaultValue={today(getLocalTimeZone()).add({ days: 7 })} />,
  Range: () => {
    const t = today(getLocalTimeZone())
    return <DateRangePicker className="w-80" label="Reporting period" defaultValue={{ start: t.subtract({ days: 30 }), end: t }} />
  },
  'Date & time': () => (
    <DatePicker
      className="w-72"
      variant="filled"
      label="Publish at"
      granularity="minute"
      hideTimeZone
      defaultValue={now(getLocalTimeZone()).add({ hours: 2 }).set({ minute: 0, second: 0, millisecond: 0 })}
      description="Posts go live at this time in your timezone."
    />
  ),
}

Source: packages/ui/src/date-picker/date-picker.tsx

Catalog

Category
date-time
Priority
Core
Primitive
react-aria
React Aria
DateRangePicker