Marigold
v18.0.0-beta.4
Marigold
v18.0.0-beta.4

Application

MarigoldProvider
RouterProvider

Layout

AppShellbeta
Aside
Aspect
Center
Columns
Container
Grid
Inline
Inset
Pagebeta
Panelbeta
Scrollable
Split
Stack
Tiles

Actions

Buttonupdated
ButtonGroupbeta
Link
LinkButton
ToggleButtonbeta

Form

Autocomplete
Calendar
Checkbox
ComboBox
DateField
DatePicker
DateRangePickerbeta
FileField
Form
NumberField
Radio
RangeCalendaralpha
SearchField
SegmentedControlbeta
Select
SelectListupdated
Slider
Switchupdated
TagFieldbeta
TextArea
TextField
TimeField

Collection

Cardupdated
Table
Tag
ActionBaralpha

Navigation

Accordion
Breadcrumbs
Pagination
Sidebarbeta
Tabs
TopNavigationbeta

Overlay

ActionMenualpha
ContextualHelp
Dialog
Drawer
Menuupdated
Toastbeta
Tooltip

Content

Badge
Descriptionalpha
Divider
EmptyStatebeta
ErrorStatebeta
Headline
Keyboardbeta
List
Loader
SectionMessage
SVG
Text
TextValuealpha
Titlealpha

Formatters

DateFormat
NumericFormat

Hooks and Utils

cn
cva
extendTheme
parseFormData
useAsyncListData
useLandmark
useListData
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.

Quick select presets

Use the presets prop to offer common ranges as a one-click list beside the calendar in the popover, such as "This week" or "Last 30 days" for a reporting period. Built-in keys ship with localized labels and correct date math, and custom presets take a label plus a range value or a resolver function. Presets that fall outside minValue/maxValue or cover an unavailable date are disabled.

Besides the range keys, the single-date built-ins (today, yesterday, tomorrow) also work here and select a one-day range. Range keys such as this-week are not available on DatePicker and Calendar, which accept only the single-date built-ins.

For custom presets, pass value as a function when the range is relative to now (for example "Next 14 days"), so it resolves at selection time instead of when the view first rendered. A plain value is right for fixed ranges. If you provide several custom presets, give each a unique id: it defaults to the label, so two presets sharing a label would collide.

Reporting period
MM/DD/YYYY
–
MM/DD/YYYY
import { DateRangePicker } from '@marigold/components';export default () => (  <DateRangePicker    label="Reporting period"    presets={[      'today',      'yesterday',      'this-week',      'next-7-days',      'next-30-days',      'this-month',      'this-quarter',    ]} // [!code highlight]  />);

Quick select on narrow screens

The picker's overlay is already a bottom sheet on small screens, so a "Quick selection" row above the grid switches the sheet to the preset list in place, with a Back row to return to the calendar. Picking a preset applies the range and returns to the calendar, and the overlay stays open.

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: 7 days 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 monthsQuick select presetsAccessibilityPropsAlternative componentsRelated