Forms

Date range picker

A date-range field: one trigger showing "start – end", a popover hosting `Calendar` in range mode.

Client componentSource

Import

import { DateRangePicker } from '@the_viveksingh/vivek-ui'

A stay

One trigger reading start – end, a popup hosting Calendar in range mode. It closes on the second date and returns focus to the field; Escape after a first click restores the last complete range instead of leaving one date of two in the form.

3 nights — the form receives stay-start and stay-end as ISO dates.

const [stay, setStay] = useState({ start: null, end: null })

<Field label="Stay">
  <DateRangePicker name="stay" value={stay} onValueChange={setStay} />
</Field>

// The form receives two ISO fields: stay-start and stay-end.
// The trigger's accessible name reads the range in words:
// "Stay: March 12, 2026 to March 15, 2026".

Bounded, weekends refused

min, max and disabledDates pass straight through to Calendar, where a disabled day is unreachable by keyboard rather than merely unclickable.

Only March 2026, and never a weekend — the calendar refuses those days rather than accepting and rejecting later.

<DateRangePicker
  min={new Date(2026, 2, 1)}
  max={new Date(2026, 2, 31)}
  disabledDates={(d) => d.getDay() === 0 || d.getDay() === 6}
  name="workshop"
/>

Props

Generated from the package's own type declarations, so this table cannot drift from the code.

Props for DateRangePicker
PropTypeDefaultDescription
valueDateRange | null—Controlled range. `end` is `null` while the user has picked only a start.
defaultValueDateRange | null——
onValueChange(value: DateRange | null) => void—Fires on every change, including the half-selected `{ start, end: null }` step, so a consumer can react to the first click. Read `end !== null` for "complete".
minDate | null——
maxDate | null——
disabledDatesDisabledDates——
weekStartsOnWeekStart——
localeDateLocale——
size'sm' | 'md' | 'lg'——
disabledboolean——
invalidboolean—Sets `aria-invalid` on the trigger. Injected by `Field`.
requiredboolean—Injected by `Field`.
namestring—Submits two hidden fields, `{name}-start` and `{name}-end`, as ISO dates — the same convention `Calendar` uses in range mode, so a form does not care which rendered it.
placeholder{ start?: string; end?: string; }—Shown in place of a missing start or end. Default `'Start date'` / `'End date'`.
format(date: Date) => string—Renders a date as the trigger's text. Default `YYYY-MM-DD`, which is deterministic — `Intl` output differs between Node builds and browsers, so a locale-aware default would hydrate differently for two of your users.
labelstring—The control's name, spoken before the current range: "Stay: 12 Mar 2026 to 15 Mar 2026". Default `'Date range'`. Prefer `aria-labelledby` (via rest) when a visible label exists.
openboolean—Controlled popup state.
defaultOpenboolean——
onOpenChange(open: boolean) => void——
sideSide——
alignAlign——
offsetnumber——
paddingnumber——
containerPortalContainer—Where the popup portals. Defaults to `document.body`.

Every remaining prop is spread onto the root element, so all standard HTML and ARIA attributes work. className and style are merged with the library's own, never replaced, and the ref forwards to the root DOM node.

Rendering