Marigold
v17.9.0
Marigold
v17.9.0

Application

MarigoldProvider
RouterProvider

Layout

AppLayoutbeta
Aside
Aspect
Breakout
Center
Columns
Container
Grid
Inline
Inset
Scrollable
Split
Stack
Tiles

Actions

ActionBaralpha
Button
Link
LinkButton
ToggleButtonbeta

Form

Autocomplete
Calendar
Checkbox
ComboBox
DateField
DatePicker
DateRangePickerbeta
FileField
Form
Multiselectdeprecated
NumberField
Radio
RangeCalendaralpha
SearchField
Select
Slider
Switch
TagFieldbeta
TextArea
TextField
TimeField

Collection

SelectList
Table
Tag

Navigation

Accordion
Breadcrumbs
Pagination
Sidebarbeta
Tabs
TopNavigationbeta

Overlay

ContextualHelp
Dialog
Drawer
Menu
Toastbeta
Tooltip

Content

Badge
Card
Divider
EmptyStatebeta
Headline
Icon
List
Loader
SectionMessage
SVG
Text

Formatters

DateFormat
NumericFormat

Hooks and Utils

cn
cva
extendTheme
parseFormData
useAsyncListData
useListData
useResponsiveValue
useTheme
VisuallyHidden
Components

DateRangePicker

Pick a start and end date through a single field.

The <DateRangePicker> component lets users enter or select a date range, a start date together with an end date, through a single field.

The two dates can be picked together on a calendar or typed directly into the field.

Anatomy

The Label states the purpose of the field. Two date inputs hold the start and the end of the range, with a separator between them. The Calendar Button opens a range calendar where the user can pick both ends visually.

LabelFieldDescriptionStart dateEnd dateSeparatorCalendar button

Appearance

The appearance of a component can be customized using the variant and size props. These props adjust the visual style and dimensions of the component, available values are based on the active theme.

The selected theme does not has any options for"variant" and "size".
Event dates
MM/DD/YYYY
–
MM/DD/YYYY
PropertyTypeDescription
variant-The available variants of this component.
size-The available sizes of this component.

Usage

The clearest signal that you want a <DateRangePicker> is the span itself. When the time between the two dates is part of what the user is deciding, a trip that lasts a week, a report that covers a quarter, a campaign that runs for ten days, the two dates work as one value and people benefit from seeing the whole stretch on a single calendar.

Choosing both ends on the same calendar also keeps that value consistent. The end can never fall before the start, and rules like a minimum number of nights or blocked dates apply to the pair at once. Two separate fields cannot do this without extra validation, and moving between two calendars makes it easy to click the wrong day once the visible month shifts.

Do

Use a <DateRangePicker> when the time between the two dates matters and people benefit from seeing the whole span on one calendar, like a booking or a reporting period.

Don't

Don't use it when only the endpoints matter, when one end can stay open, or when the dates are unrelated. Reach for a single DatePicker or two independent fields instead.

The same booking captures one value on the left and two on the right. The range picker holds the whole trip in a single control and lets people pick both ends on one calendar, while the separate fields treat arrival and departure as unrelated inputs.

One range picker
Trip dates
MM/DD/YYYY
–
MM/DD/YYYY
Two separate fields
Arrival
MM/DD/YYYY
Departure
MM/DD/YYYY
import {  DatePicker,  DateRangePicker,  Inline,  Stack,  Text,} from '@marigold/components';export default () => (  <Inline space={12} alignY="top">    <Stack space={3}>      <Text weight="semibold">One range picker</Text>      <DateRangePicker label="Trip dates" /> {/* [!code highlight] */}    </Stack>    <Stack space={3}>      <Text weight="semibold">Two separate fields</Text>      <Inline space={4}>        <DatePicker label="Arrival" width="fit" />        <DatePicker label="Departure" width="fit" />      </Inline>    </Stack>  </Inline>);

@internationalized/date

Marigold represents dates with the DateValue type from @internationalized/date rather than the native JavaScript Date, which avoids the timezone and parsing problems that come with Date. It is a peer dependency, so install it if it is not already in your project.

Limiting the range

Often only part of the calendar makes sense. A booking cannot start in the past, and a report cannot reach into the future. Set minValue and maxValue to fence the selectable window, and the calendar prevents anything outside it.

Booking window
MM/DD/YYYY
–
MM/DD/YYYY
import { getLocalTimeZone, today } from '@internationalized/date';import { DateRangePicker } from '@marigold/components';export default () => {  const now = today(getLocalTimeZone());  return (    <DateRangePicker      label="Booking window"      minValue={now} // [!code highlight]      maxValue={now.add({ months: 6 })} // [!code highlight]    />  );};

Range length

A range often has rules about how long it can be, such as a stay of at least two nights or at most two weeks. Read the selected value, compare its end to its start, and set error with an errorMessage when the length falls outside the allowed bounds.

Stay
MM/DD/YYYY
–
MM/DD/YYYY
import type { DateValue } from '@internationalized/date';import { useState } from 'react';import { DateRangePicker } from '@marigold/components';const MIN_NIGHTS = 2;const MAX_NIGHTS = 14;const getErrorMessage = (nights: number | null): string | undefined => {  if (nights === null) return undefined;  if (nights < MIN_NIGHTS)    return `A stay must be at least ${MIN_NIGHTS} nights.`;  if (nights > MAX_NIGHTS) return `A stay can be at most ${MAX_NIGHTS} nights.`;  return undefined;};export default () => {  const [value, setValue] = useState<{    start: DateValue;    end: DateValue;  } | null>(null);  const nights = value ? value.end.compare(value.start) : null; // [!code highlight]  const message = getErrorMessage(nights);  return (    <DateRangePicker      label="Stay"      value={value}      onChange={setValue}      error={Boolean(message)} // [!code highlight]      errorMessage={message} // [!code highlight]    />  );};

Blocking unavailable dates

Some days inside the allowed window still cannot be chosen, such as nights that are already booked or public holidays. Return true from dateUnavailable for any date that should be disabled.

Stay dates
MM/DD/YYYY
–
MM/DD/YYYY
import { getLocalTimeZone, today } from '@internationalized/date';import { DateRangePicker } from '@marigold/components';export default () => {  const now = today(getLocalTimeZone());  // Nights that are already booked and cannot be part of a new stay.  const booked = [    now.add({ days: 3 }),    now.add({ days: 4 }),    now.add({ days: 5 }),  ];  return (    <DateRangePicker      label="Stay dates"      minValue={now}      dateUnavailable={date => booked.some(d => date.compare(d) === 0)} // [!code highlight]    />  );};

Showing multiple months

Ranges that stretch across several months are awkward to pick one month at a time, which is common when planning a holiday or a quarter. Set visibleDuration to show up to three months at once. On small screens the calendar always falls back to a single month inside a tray.

Vacation
MM/DD/YYYY
–
MM/DD/YYYY
import { DateRangePicker } from '@marigold/components';export default () => (  <DateRangePicker    label="Vacation"    visibleDuration={{ months: 2 }} // [!code highlight]  />);

Narrow screens

The field lays out two date inputs, a separator and the calendar button next to each other, so it needs roughly 260px of width for its content. It holds that minimum even when the surrounding layout is narrower and overflows rather than crushing the inputs together. Because of this it is not suited to very small viewports such as a 320px screen. Give it horizontal room, or reach for a single DatePicker when space is tight.

Accessibility

Picking a range on the calendar can be slow for people who rely on a keyboard or a screen reader, and people who work with dates all day often prefer to type. For both groups the field stays fully usable without ever opening the calendar. Every segment can be edited directly, and a full date can be pasted into either the start or the end input. The component parses the pasted text, validates it, and fills in that end of the range. Pasted text is recognized in these formats:

  • ISO format: 2023-12-25
  • European format: 25.12.2023 or 25/12/2023
  • US format: 12/25/2023 or 12-25-2023

Unrecognized or invalid text is ignored, so the field never ends up in a broken state.

Props

Did you know? You can explore, test, and customize props live in Marigold's storybook. Watch the effects they have in real-time!
View DateRangePicker stories

Prop

Type

Accessibility props (4)

Prop

Type

DOM event handlers (64)

Prop

Type

Alternative components

  • DatePicker: Pick a single date through a field with a calendar popover.

  • RangeCalendar: Select a date range from a calendar that is always visible.

  • DateField: Let users type a single date directly.

Related

Forms

How to structure, validate, and submit forms with Marigold.

Form Fields

Learn how to build forms.
Last update: 2 minutes ago

DatePicker

Component used to pick date value.

FileField

A form component for uploading files with drag and drop support.

On this page

AnatomyAppearanceUsageLimiting the rangeRange lengthBlocking unavailable datesShowing multiple monthsAccessibilityPropsAlternative componentsRelated