Material-UI pickers
v4.0.0-alpha.12

Date range picker#

⚠️⚠️ The date range picker is unstable, it's not suitable for usage in production. ⚠️⚠️

The date range picker will be made available in the coming months for production use as part of a paid extension to the community edition (MIT license) of Material-UI. This paid extension will include advanced components (rich data grid, date range picker, tree view drag & drop, etc.). Pricing for early access will start with an affordable plan.

The date range pickers let users select a range of dates.

Basic usage#

Basic DateRangePicker example, make sure that you can pass almost any prop of DatePicker

import * as React from "react";
import TextField from "@material-ui/core/TextField";
import { DateRangePicker, DateRange, DateRangeDelimiter } from "@material-ui/pickers";

export default function BasicDateRangePicker() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  return (
    <DateRangePicker
      startText="Check-in"
      endText="Check-out"
      value={value}
      onChange={(newValue) => setValue(newValue)}
      renderInput={(startProps, endProps) => (
        <React.Fragment>
          <TextField {...startProps} />
          <DateRangeDelimiter> to </DateRangeDelimiter>
          <TextField {...endProps} />
        </React.Fragment>
      )}
    />
  );
}

mm/dd/yyyy

to

mm/dd/yyyy

Responsiveness#

The date range picker component is designed and optimized for the device it runs on.

  • The "Mobile" version works best for touch devices and small screens.
  • The "Desktop" version works best for mouse devices and large screens.

By default, the DateRangePicker component uses a @media (pointer: fine) media query to determine which version to use. This can be customized by desktopModeMediaQuery prop.

import * as React from "react";
import TextField from "@material-ui/core/TextField";
import {
  MobileDateRangePicker,
  DateRangeDelimiter,
  DesktopDateRangePicker,
  DateRange,
} from "@material-ui/pickers";

export default function ResponsiveDateRangePicker() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  return (
    <React.Fragment>
      <MobileDateRangePicker
        startText="Mobile start"
        value={value}
        onChange={(newValue) => setValue(newValue)}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <DateRangeDelimiter> to </DateRangeDelimiter>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
      <DesktopDateRangePicker
        startText="Desktop start"
        value={value}
        onChange={(newValue) => setValue(newValue)}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <DateRangeDelimiter> to </DateRangeDelimiter>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
    </React.Fragment>
  );
}

mm/dd/yyyy

to

mm/dd/yyyy

mm/dd/yyyy

to

mm/dd/yyyy

Different amount of calendars#

Make sure that calendars prop is working only for desktop mode.

import * as React from "react";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import TextField from "@material-ui/core/TextField";
import { DateRangePicker, DateRangeDelimiter, DateRange } from "@material-ui/pickers";

export default function CalendarsDateRangePicker() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  return (
    <Grid container direction="column" alignItems="center">
      <Typography gutterBottom> 1 calendar </Typography>
      <DateRangePicker
        calendars={1}
        value={value}
        onChange={(newValue) => setValue(newValue)}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <DateRangeDelimiter> to </DateRangeDelimiter>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
      <Typography gutterBottom> 2 calendars</Typography>
      <DateRangePicker
        calendars={2}
        value={value}
        onChange={(newValue) => setValue(newValue)}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <DateRangeDelimiter> to </DateRangeDelimiter>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
      <Typography gutterBottom> 3 calendars</Typography>
      <DateRangePicker
        calendars={3}
        value={value}
        onChange={(newValue) => setValue(newValue)}
        renderInput={(startProps, endProps) => (
          <React.Fragment>
            <TextField {...startProps} />
            <DateRangeDelimiter> to </DateRangeDelimiter>
            <TextField {...endProps} />
          </React.Fragment>
        )}
      />
    </Grid>
  );
}

1 calendar

mm/dd/yyyy

to

mm/dd/yyyy

2 calendars

mm/dd/yyyy

to

mm/dd/yyyy

3 calendars

mm/dd/yyyy

to

mm/dd/yyyy

Disabling dates#

Disabling dates performs just like in simple DatePicker

import * as React from "react";
import addWeeks from "date-fns/addWeeks";
import TextField from "@material-ui/core/TextField";
import { Dayjs } from "dayjs";
import { Moment } from "moment";
import { DateTime } from "luxon";
import { DateRangePicker, DateRangeDelimiter, DateRange } from "@material-ui/pickers";
// TODO remove relative import
import { makeJSDateObject } from "../../../utils/helpers";

function getWeeksAfter(date: Moment | DateTime | Dayjs | Date, amount: number) {
  // TODO: replace with implementation for your date library
  return date ? addWeeks(makeJSDateObject(date), amount) : undefined;
}

export default function MinMaxDateRangePicker() {
  const [value, setValue] = React.useState<DateRange<Date>>([null, null]);

  return (
    <DateRangePicker
      disablePast
      value={value}
      // @ts-ignore
      maxDate={getWeeksAfter(value[0], 4)}
      onChange={(newValue) => setValue(newValue)}
      renderInput={(startProps, endProps) => (
        <React.Fragment>
          <TextField {...startProps} />
          <DateRangeDelimiter> to </DateRangeDelimiter>
          <TextField {...endProps} />
        </React.Fragment>
      )}
    />
  );
}

mm/dd/yyyy

to

mm/dd/yyyy

Custom input component#

You can customize rendering input by renderInput prop. For DateRangePicker it takes 2 parameters – for start and end input respectively. So if you need to render custom input make sure you will spread ref and inputProps correctly to the input components.

import * as React from "react";
import { DateRangePicker, DateRange } from "@material-ui/pickers";

export default function CustomRangeInputs() {
  const [selectedDate, handleDateChange] = React.useState<DateRange<Date>>([null, null]);

  return (
    <DateRangePicker
      label="Advanced keyboard"
      value={selectedDate}
      onChange={(date) => handleDateChange(date)}
      renderInput={(startProps, endProps) => (
        <React.Fragment>
          <input
            ref={startProps.inputRef as React.Ref<HTMLInputElement>}
            {...startProps.inputProps}
          />
          <input ref={endProps.inputRef as React.Ref<HTMLInputElement>} {...endProps.inputProps} />
        </React.Fragment>
      )}
    />
  );
}

Static mode#

It is possible to render any picker without modal or popper. For that use StaticDateRangePicker.

API#