Skip to content

Date & time

Date range

Two dates, inclusive at both ends, with consumer-defined presets beside the calendar. LUC hard-codes no business windows: “last 7 days” is a preset you pass in, not a feature of the component.

Examples

Presets and a calendar

Presets are a typed list of label plus value (or a factory that receives today). The active preset is derived from the value — never a second piece of state that can drift.

Choose a preset, type the dates, or pick a range in the calendar.

value: 2026-09-01 → 2026-09-26

A range for a record, not a filter

No presets, no Today action, one visible month. A booking or a reporting period is a decision, not a browsing aid.

Billing runs on the first working day after the end date.

A same-day range is allowed; 21–24 September is not.

Sizes and states

The same shell as every other control: hover steps one border, focus draws the ring, invalid is negative without a red banner.

Default

Empty

Invalid

Disabled

Small

One month

the mobile layout

Any preset shape, no business logic

A preset can be a fixed range or a factory. This one shows what a consumer-owned “rolling” window looks like — the calculation lives in the page, not in the component.

Both presets are computed in the page from the injected today.

Usage

import { DateRangePicker } from "@luc/ui";
<DateRangePicker
  aria-label="Reporting period"
  value={range}
  onValueChange={setRange}
  todayValue={today}
  months={2}
/>

`value` is `{ start, end }` with both ends inclusive, or `null` when either end is missing. Pass `todayValue` so a screenshot, a test or a server render does not change meaning at midnight.

API

Read from the published TypeScript API, so a prop that is not listed here does not exist and a default that is listed is the one the compiler sees.

DateRangePicker shares its module with DatePicker, so the exports table below is the shared one; its own props table comes first, and the rest of the module is folded underneath it.

Exported symbols
ExportKindSignature
DateField60 documented props<T extends DateValue = DateValue>({ size, invalid, disabled, readOnly, className, trailingAction, ...props }: DateFieldProps<T>) => import("@types/react").JSX.Element
DatePicker60 documented props<T extends DateValue = DateValue>({ onValueChange, size, invalid, disabled, readOnly, required, locale, viewSwitch, showTodayAction, showClearAction, calendarButtonLabel, footer, className, todayValu…
DateRangePicker60 documented props<T extends DateValue = DateValue>({ onValueChange, size, invalid, disabled, readOnly, required, locale, months, presets, showTodayAction, showClearAction, calendarButtonLabel, footer, className, toda…

DateRangePicker props

Type: DateRangePickerProps<T>

Values the compiler reads from the declaration.

DateRangePicker props
PropTypeDefaultNotes
allowsNonContiguousRanges?inheritedboolean | undefined—When combined with `isDateUnavailable`, determines whether non-contiguous ranges, i.e. ranges containing unavailable dates, may be selected.
aria-describedby?inheritedstring | undefined—Identifies the element (or elements) that describes the object.
aria-details?inheritedstring | undefined—Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-label?inheritedstring | undefined—Defines a string value that labels the current element.
aria-labelledby?inheritedstring | undefined—Identifies the element (or elements) that labels the current element.
autoFocus?inheritedboolean | undefined—Whether the element should receive focus on render.
calendarButtonLabel?string | undefined—
className?string | undefined—
defaultOpen?inheritedboolean | undefined—Whether the overlay is open by default (uncontrolled).
defaultValue?inheritedRangeValue<T> | null | undefined—The default value (uncontrolled).
dir?inheritedstring | undefined—
disabled?boolean | undefined—
firstDayOfWeek?inherited"sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | undefined—The day that starts the week.
footer?ReactNode—
form?inheritedstring | undefined—The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs…
granularity?inheritedGranularity | undefined—Determines the smallest unit that is displayed in the date picker. By default, this is `"day"` for dates, and `"minute"` for times.
hidden?inheritedboolean | undefined—
hideTimeZone?inheritedboolean | undefinedWhether to hide the time zone abbreviation.
hourCycle?inherited24 | 12 | undefined—Whether to display the time in 12 or 24 hour format. By default, this is determined by the user's locale.
id?inheritedstring | undefined—The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
inert?inheritedboolean | undefined—
invalid?boolean | undefined—
isDateUnavailable?inherited((date: DateValue, anchorDate: CalendarDate | null) => boolean) | undefined—Callback that is called for each date of the calendar. If it returns true, then the date is unavailable.
isOpen?inheritedboolean | undefined—Whether the overlay is open by default (controlled).
lang?inheritedstring | undefined—
locale?string | undefined—
maxValue?inheritedDateValue | null | undefined—The maximum allowed date that a user may select.
minValue?inheritedDateValue | null | undefined—The minimum allowed date that a user may select.
months?1 | 2 | undefined—Months shown at once. Default `2`; the caller drops to 1 on mobile.
onAnimationEnd?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationEndCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIteration?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIterationCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStart?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStartCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAuxClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onAuxClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onBlur?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element loses focus.
onClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenu?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenuCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onFocus?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element receives focus.
onFocusChange?inherited((isFocused: boolean) => void) | undefined—Handler that is called when the element's focus status changes.
onGotPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onGotPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onKeyDown?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is pressed.
onKeyUp?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is released.
onLostPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onLostPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onMouseDown?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseDownCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseEnter?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseLeave?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMove?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMoveCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOut?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOutCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
DateField props60 props

DateField props

Type: DateFieldProps<T>

Values the compiler reads from the declaration.

DateField props
PropTypeDefaultNotes
aria-describedby?inheritedstring | undefined—Identifies the element (or elements) that describes the object.
aria-details?inheritedstring | undefined—Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-label?inheritedstring | undefined—Defines a string value that labels the current element.
aria-labelledby?inheritedstring | undefined—Identifies the element (or elements) that labels the current element.
autoComplete?inheritedstring | undefined—Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete…
autoFocus?inheritedboolean | undefined—Whether the element should receive focus on render.
className?string | undefined—
defaultValue?inheritedT | null | undefined—The default value (uncontrolled).
dir?inheritedstring | undefined—
disabled?boolean | undefined—
form?inheritedstring | undefined—The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs…
granularity?inheritedGranularity | undefined—Determines the smallest unit that is displayed in the date picker. By default, this is `"day"` for dates, and `"minute"` for times.
hidden?inheritedboolean | undefined—
hideTimeZone?inheritedboolean | undefinedWhether to hide the time zone abbreviation.
hourCycle?inherited24 | 12 | undefined—Whether to display the time in 12 or 24 hour format. By default, this is determined by the user's locale.
id?inheritedstring | undefined—The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
inert?inheritedboolean | undefined—
invalid?boolean | undefined—
isDateUnavailable?inherited((date: DateValue) => boolean) | undefined—Callback that is called for each date of the calendar. If it returns true, then the date is unavailable.
isRequired?inheritedboolean | undefined—Whether user input is required on the input before form submission.
lang?inheritedstring | undefined—
locale?string | undefined—BCP-47 locale for segment order, weekday names and the visible month.
maxValue?inheritedDateValue | null | undefined—The maximum allowed date that a user may select.
minValue?inheritedDateValue | null | undefined—The minimum allowed date that a user may select.
name?inheritedstring | undefined—The name of the input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname).
onAnimationEnd?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationEndCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIteration?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIterationCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStart?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStartCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAuxClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onAuxClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onBlur?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element loses focus.
onChange?inherited((value: MappedDateValue<T> | null) => void) | undefined—Handler that is called when the value changes.
onClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenu?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenuCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onFocus?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element receives focus.
onFocusChange?inherited((isFocused: boolean) => void) | undefined—Handler that is called when the element's focus status changes.
onGotPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onGotPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onKeyDown?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is pressed.
onKeyUp?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is released.
onLostPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onLostPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onMouseDown?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseDownCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseEnter?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseLeave?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMove?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMoveCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOut?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOutCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOver?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOverCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseUp?inheritedMouseEventHandler<HTMLDivElement> | undefined—
DatePicker props60 props

DatePicker props

Type: DatePickerProps<T>

Values the compiler reads from the declaration.

DatePicker props
PropTypeDefaultNotes
aria-describedby?inheritedstring | undefined—Identifies the element (or elements) that describes the object.
aria-details?inheritedstring | undefined—Identifies the element (or elements) that provide a detailed, extended description for the object.
aria-label?inheritedstring | undefined—Defines a string value that labels the current element.
aria-labelledby?inheritedstring | undefined—Identifies the element (or elements) that labels the current element.
autoComplete?inheritedstring | undefined—Describes the type of autocomplete functionality the input should provide if any. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefautocomplete…
autoFocus?inheritedboolean | undefined—Whether the element should receive focus on render.
calendarButtonLabel?string | undefined—Accessible name for the calendar button. Localized by React Aria by default.
className?string | undefined—
defaultOpen?inheritedboolean | undefined—Whether the overlay is open by default (uncontrolled).
defaultValue?inheritedT | null | undefined—The default value (uncontrolled).
dir?inheritedstring | undefined—
disabled?boolean | undefined—
firstDayOfWeek?inherited"sun" | "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | undefined—The day that starts the week.
footer?ReactNode—Extra footer content beside the quick actions.
form?inheritedstring | undefined—The `<form>` element to associate the input with. The value of this attribute must be the id of a `<form>` in the same document. See [MDN](https://developer.mozilla.org/en-US/docs…
granularity?inheritedGranularity | undefined—Determines the smallest unit that is displayed in the date picker. By default, this is `"day"` for dates, and `"minute"` for times.
hidden?inheritedboolean | undefined—
hideTimeZone?inheritedboolean | undefinedWhether to hide the time zone abbreviation.
hourCycle?inherited24 | 12 | undefined—Whether to display the time in 12 or 24 hour format. By default, this is determined by the user's locale.
id?inheritedstring | undefined—The element's unique identifier. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/id).
inert?inheritedboolean | undefined—
invalid?boolean | undefined—
isDateUnavailable?inherited((date: DateValue) => boolean) | undefined—Callback that is called for each date of the calendar. If it returns true, then the date is unavailable.
isOpen?inheritedboolean | undefined—Whether the overlay is open by default (controlled).
lang?inheritedstring | undefined—
locale?string | undefined—
maxValue?inheritedDateValue | null | undefined—The maximum allowed date that a user may select.
minValue?inheritedDateValue | null | undefined—The minimum allowed date that a user may select.
name?inheritedstring | undefined—The name of the input element, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#htmlattrdefname).
onAnimationEnd?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationEndCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIteration?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationIterationCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStart?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAnimationStartCapture?inheritedAnimationEventHandler<HTMLDivElement> | undefined—
onAuxClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onAuxClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onBlur?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element loses focus.
onClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenu?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onContextMenuCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClick?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onDoubleClickCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onFocus?inherited((e: FocusEvent<Element, Element>) => void) | undefined—Handler that is called when the element receives focus.
onFocusChange?inherited((isFocused: boolean) => void) | undefined—Handler that is called when the element's focus status changes.
onGotPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onGotPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onKeyDown?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is pressed.
onKeyUp?inherited((e: KeyboardEvent) => void) | undefined—Handler that is called when a key is released.
onLostPointerCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onLostPointerCaptureCapture?inheritedPointerEventHandler<HTMLDivElement> | undefined—
onMouseDown?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseDownCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseEnter?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseLeave?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMove?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseMoveCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOut?inheritedMouseEventHandler<HTMLDivElement> | undefined—
onMouseOutCapture?inheritedMouseEventHandler<HTMLDivElement> | undefined—

Guidelines

Do

  • Pass the business windows in as `presets`. A range component that knew what “quarter to date” meant would have to know what a quarter is, which is the consumer's domain.
  • Read the selected range from `value` rather than mirroring it in a second state — an active preset is derived from the range, and two copies of the same fact drift.
  • Use `DateRangePicker` when the two ends belong to one decision (a reporting period, a booking); use two `DatePicker`s when they are independent fields.

Don't

  • Sending a range to a query as two instants. `09-01 → 09-18` is a pair of dates; whether the end day includes its last second is a query decision, and `.endOf("day")` belongs at the boundary, not in the control.
  • Showing a range picker where a single date is what the user is choosing — two calendars for one decision is four times the surface and the same answer.

Accessibility: the two ends are one field group with a labelled start and end segment, so a keyboard user moves through six segments in reading order and a screen reader announces which end is focused; `isDateUnavailable` keeps blocked days focusable and announced rather than removing them from the grid.

Luc UI v1.0Date rangedark theme