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}
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}
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" | ... 159 more ... | FunctionComponent<...> |