Skip to Content

Date picker

Used for selecting dates on a calendar to set timeframes, deadlines, and more.

import * as React from 'react';
import { DatePicker, Popover, IconButton } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const [visible, setVisible] = React.useState(false);
  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            showYearSelection
            date={currentDate}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toDateString()}</span>
    </div>
  );
};

When a user needs to schedule deadlines, timeframes, or for age verification purposes, we provide them with a date picker. It behaves much like a select menu. We currently have three different types of date pickers.

Usage

The DatePicker component allows the user to pick a date from the calendar and skip a month at a time.

This component is recommended to be used inside the Popover component, which takes care for placement, collision handling, focus management, outside clicks, and other interaction details.

import * as React from 'react';
import { DatePicker, IconButton, Popover } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const [visible, setVisible] = React.useState(false);
  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            date={currentDate}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toDateString()}</span>
    </div>
  );
};

If you would rather see an example of the date picker being used on its own, look at the standalone usage.

Note: The showDatesOutsideMonth prop is recommended to be set to false, so that dates that are not in the currently selected month are not displayed. Currently, this prop defaults to true for backwards compatibility reasons.

Localized

You are able to create a localized version of the date picker that uses local names for week days and months.

import * as React from 'react';
import {
  DatePicker,
  IconButton,
  Popover,
  generateLocalizedStrings,
} from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const [visible, setVisible] = React.useState(false);
  const localizedNames = generateLocalizedStrings('ja');
  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            date={currentDate}
            localizedNames={localizedNames}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toDateString()}</span>
    </div>
  );
};

Date + time selection

If you need to include the time, there are multiple ways to do so. Below is the default variant, which uses twenty-four hour time.

import * as React from 'react';
import { DatePicker, Popover, IconButton } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const [visible, setVisible] = React.useState(false);
  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            date={currentDate}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            showTime={true}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toString()}</span>
    </div>
  );
};

And here is the variant that uses twelve-hour time with meridiem:

import * as React from 'react';
import { DatePicker, Popover, IconButton } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(
    new Date(2021, 4, 11, 14, 30, 0),
  );
  const [visible, setVisible] = React.useState(false);
  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            date={currentDate}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            showTime={true}
            useCombinedRenderer={true}
            minuteStep={30}
            use12Hours={true}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toString()}</span>
    </div>
  );
};

Date range

There may be some cases where you need to display a range of dates. When this occurs, the selection box spans the entirety of the date range.

import * as React from 'react';
import { DatePicker, IconButton, Popover } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const startDate = new Date(2023, 6, 5, 14, 55, 22);
  const endDate = new Date(2023, 6, 12, 14, 55, 27);

  const [visible, setVisible] = React.useState(false);

  return (
    <Popover
      content={
        <DatePicker
          enableRangeSelect={true}
          startDate={startDate}
          endDate={endDate}
          onChange={() => {
            setVisible(false);
          }}
          setFocus
          showDatesOutsideMonth={false}
        />
      }
      placement='bottom-start'
      visible={visible}
      onVisibleChange={setVisible}
    >
      <IconButton label='Choose date'>
        <SvgCalendar />
      </IconButton>
    </Popover>
  );
};

Some dates disabled

You might also need to have certain dates disabled, in case the range of dates that can be selected for your purpose is limited.

import * as React from 'react';
import { DatePicker, IconButton, Popover } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const startDate = new Date(2023, 6, 5, 14, 55, 22);
  const endDate = new Date(2023, 6, 12, 14, 55, 27);

  const isDateDisabled = (date) => {
    if (date.getMonth() !== 6) {
      return true;
    }
    if (date.getDate() < 5 || date.getDate() > 19) {
      return true;
    }
    return false;
  };

  const [visible, setVisible] = React.useState(false);

  return (
    <Popover
      content={
        <DatePicker
          enableRangeSelect={true}
          startDate={startDate}
          endDate={endDate}
          isDateDisabled={isDateDisabled}
          onChange={() => {
            setVisible(false);
          }}
          setFocus
          showDatesOutsideMonth={false}
        />
      }
      placement='bottom-start'
      visible={visible}
      onVisibleChange={setVisible}
    >
      <IconButton label='Choose date'>
        <SvgCalendar />
      </IconButton>
    </Popover>
  );
};

Year skipping

To improve user experience, date pickers support year skipping buttons. Clicking on the double chevron icon will move the calendar a full year forward or back.

import * as React from 'react';
import { DatePicker, Popover, IconButton } from '@itwin/itwinui-react';
import { SvgCalendar } from '@itwin/itwinui-icons-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());
  const [visible, setVisible] = React.useState(false);

  return (
    <div className='demo-container'>
      <Popover
        content={
          <DatePicker
            showYearSelection
            date={currentDate}
            onChange={(date) => {
              setCurrentDate(date);
              setVisible(false);
            }}
            setFocus
            showDatesOutsideMonth={false}
          />
        }
        placement='bottom-start'
        visible={visible}
        onVisibleChange={setVisible}
      >
        <IconButton label='Choose date'>
          <SvgCalendar />
        </IconButton>
      </Popover>
      <span>{currentDate.toDateString()}</span>
    </div>
  );
};

Standalone usage

The DatePicker does not always need to be used within its own popover. You can instead display it as part of a larger interface containing interconnected controls.

You can set applyBackground={false} to make the DatePicker blend into its surroundings. This is useful when the surrounding UI already brings its own background-color and border.

import * as React from 'react';
import { DatePicker, Surface } from '@itwin/itwinui-react';

export default () => {
  const [currentDate, setCurrentDate] = React.useState(new Date());

  return (
    <Wrapper>
      <DatePicker
        showYearSelection
        date={currentDate}
        onChange={(date) => {
          setCurrentDate(date);
        }}
        applyBackground={false}
        showDatesOutsideMonth={false}
      />
      <div className='demo-label'>{currentDate.toDateString()}</div>
    </Wrapper>
  );
};

function Wrapper({ children }) {
  return <Surface className='demo-container'>{children}</Surface>;
}

Props

Prop Description Default
date
Selected date.
Date
localizedNames
Pass localized week days (start from sunday) and months. Use helper function generateLocalizedStrings to generate strings using Intl.DateTimeFormat.
DatePickerLocalizedNames
setFocus
Set focus on selected day or today.
boolean
false
showTime
Show time picker near the calendar.
boolean
false
showYearSelection
Show additional buttons to select year.
boolean
false
monthYearProps
Allows props to be passed for calendar month year, referring to the div that wraps around the month/year and the next/previous buttons.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
monthProps
Allows props to be passed for only month, referring to span that wraps around the month title.
DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>
weekDayProps
Allows props to be passed for week days, referring to div that wraps around the week day title.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
dayProps
Allows props to be passed for individual day , referring to div element the wraps around single day number.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
calendarProps
Allows props to be passed for calendar, referring to div that is used for listbox for wraping days and weeks.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
weekProps
Allows props to be passed for weeks, referring to div that wraps around weeks.
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>
isDateDisabled
Will disable dates for which this function returns true. Disabled dates cannot be selected.
(date: Date) => boolean
applyBackground
Whether there is a background, border, shadow, etc.
Should be set to true if used in a popover that doesn't have its own background, or set to false if the popover has its own background or embedding within a page.
boolean
true
showDatesOutsideMonth
Whether dates outside the current month should be displayed (in a muted text style).
It is recommended to set this to false. Currently it defaults to true for backward compatibility.
boolean
true
enableRangeSelect
Enable date range support.
boolean
false
startDate
Selected start date
Date
endDate
Selected end date
Date
onChange
Callback when date is changed.
((date: Date) => void) | ((startDate: Date, endDate: Date) => void)
use12Hours
Format of the time. 12h or 24h.
boolean
false
precision
Precision of the time.
Precision
'minutes'
hourStep
Change step of the hours displayed.
number
1
minuteStep
Change step of the minutes displayed.
number
1
secondStep
Change step of the seconds displayed.
number
1
hourRenderer
Custom hour cell renderer.
(date: Date) => ReactNode
(date: Date) => date.getHours().toLocaleString(undefined, { minimumIntegerDigits: 2 })
minuteRenderer
Custom minute cell renderer.
(date: Date) => ReactNode
(date: Date) => date.getMinutes().toLocaleString(undefined, { minimumIntegerDigits: 2 })
secondRenderer
Custom second cell renderer.
(date: Date) => ReactNode
(date: Date) => date.getSeconds().toLocaleString(undefined, { minimumIntegerDigits: 2 })
meridiemRenderer
Custom AM/PM cell renderer.
(meridiem: MeridiemType) => ReactNode
(meridiem: MeridiemType) => meridiem
useCombinedRenderer
Use combined time renderer. Combines hour, minute, and seconds into one column. WARNING: Using the combined renderer with a precision of 'seconds' along with small time steps (hourStep, minuteStep, and especially secondStep) can result in slow performance!
boolean
false
combinedRenderer
Custom combined time renderer. Default returns time in HH:MM:SS format
(date: Date, precision: Precision) => ReactNode
(date: Date, precision: Precision) => { let dateString = ''; switch (precision) { case 'seconds': dateString = ':' + date.getSeconds().toLocaleString(undefined, { minimumIntegerDigits: 2 }); case 'minutes': dateString = ':' + date.getMinutes().toLocaleString(undefined, { minimumIntegerDigits: 2 }) + dateString; case 'hours': dateString = date.getHours().toLocaleString(undefined, { minimumIntegerDigits: 2 }) + dateString; } return dateString; }
as
"symbol" | "object" | "div" | "a" | "abbr" | "address" | "area" | "article" | "aside" | "audio" | "b" | "base" | "bdi" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | ... 158 more ... | FunctionComponent<...>