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<...> |