An accessible, internationalizable React datepicker. Demo.
yarn add @reecelucas/react-datepicker
<DatePicker onSelect={date => console.log(date)}>
<DatePickerInput />
<DatePickerCalendar>
<DatePickerMonth />
<DatePickerButton updateMonth={({ prev }) => prev()}>
Prev Month
</DatePickerButton>
<DatePickerButton updateMonth={({ next }) => next()}>
Next Month
</DatePickerButton>
<DatePickerTable />
</DatePickerCalendar>
</DatePicker>
<DatePicker
initialDate={new Date(2020, 10, 10)}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
<DatePicker
minDate={new Date(2020, 0, 1)}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
<DatePicker
maxDate={new Date(2020, 0, 1)}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
<DatePicker
minDate={new Date(Date.now())}
maxDate={new Date(2020, 0, 1)}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
<DatePicker
excludeDates={[new Date(2019, 6, 1), new Date(2019, 6, 2)]}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
<DatePicker
includeDates={[new Date(2019, 6, 1), new Date(2019, 6, 2)]}
onSelect={date => console.log(date)}
>
{/* ... */}
</DatePicker>
Import the required date-fns locale
and make sure to render a custom aria label for each day, using the renderDayLabel
prop.
import { format } from 'date-fns';
import locale from 'date-fns/locale/fr';
<DatePicker
locale={locale}
onSelect={date => console.log(date)}
>
{/* ... */}
<DatePickerCalendar>
{/* ... */}
<DatePickerTable
renderDayLabel={({ date, isSelected, isSelectable }) => {
const status = isSelected ? 'Sélectionné. ' : `${isSelectable ? 'Disponible. ' : 'Indisponible. '}`;
return `${status}${format(date, 'eeee, do MMMM yyyy', { locale })}.`;
}}
/>
</DatePickerCalendar>
</DatePicker>
Pass a valid date-fns format
string.
<DatePicker onSelect={date => console.log(date)}>
<DatePickerInput />
<DatePickerCalendar>
<DatePickerMonth dateFormat={'MMM, yyyy'} />
{/* ... */}
</DatePickerCalendar>
</DatePicker>
import { getDate, isWeekend } from 'date-fns';
<DatePicker onSelect={date => console.log(date)}>
{/* ... */}
<DatePickerCalendar>
{/* ... */}
<DatePickerTable
renderDayContent={date => (
<span style={{ background: isWeekend(date) ? 'pink' : 'transparent' }}>
{getDate(date)}
</span>
)}
/>
</DatePickerCalendar>
</DatePicker>
Pass a valid date-fns format
string.
<DatePicker onSelect={date => console.log(date)}>
<DatePickerInput dateFormat={'MM/dd/yyyy'} />
{/* ... */}
</DatePicker>
The DatePickerInput
includes an aria-describedby
attribute that references
a visually hidden aria message (for use by screen readers). The default message is:
<>
<p>
Press the down arrow key to interact with the calendar and select a date.
The following keyboard shortcuts can be used to change dates.
</p>
<ul>
<li>Enter Key: select the date in focus.</li>
<li>
Right and left arrow keys: Move backward (left) and forward (right) by
one day.
</li>
<li>
Up and down arrow keys: Move backward (up) and forward (down) by one
week.
</li>
<li>Page up and page down keys: Switch months.</li>
<li>Home and end keys: go to the first or last day of a week.</li>
<li>Escape key: Return to the date input field.</li>
</ul>
</>
But you can render a custom message (E.g. written in another language if you're
passing a locale
) by passing a render function...
const renderScreenReaderMsg = () => (
<p>
I'm a custom screen reader message. I should describe how to interact with
the date picker, playing special attention to the keyboard shortcuts that
are available. This message won't be visible in the UI.
</p>
);
<DatePicker onSelect={date => console.log(date)}>
<DatePickerInput screenReaderMessage={renderScreenReaderMsg} />
{/* ... */}
</DatePicker>
...Or by passing a JSX element
<DatePicker onSelect={date => console.log(date)}>
<DatePickerInput
screenReaderMessage={
<p>
I'm a custom screen reader message. I should describe how to interact with
the date picker, playing special attention to the keyboard shortcuts that
are available. This message won't be visible in the UI.
</p>
}
/>
{/* ... */}
</DatePicker>
children: React.ReactNode;
onSelect: (selectedDate: Date) => void;
initialDate?: Date; // Defaults to new Date(Date.now())
minDate?: Date;
maxDate?: Date;
excludeDates?: Date[];
includeDates?: Date[];
locale?: Locale; // date-fns `locale` object
Any props not listed above will be spread onto the underlying
DatePicker
element.
dateFormat?: string; // date-fns `format` string
screenReaderMessage?: JSX.Element | () => JSX.Element;
Any props not listed above will be spread onto the underlying
DatePickerInput
element.
children: React.ReactNode;
Any props not listed above will be spread onto the underlying
DatePickerCalendar
element.
children?: (formattedDate: string) => JSX.Element;
dateFormat?: string; // date-fns `format` string
Any props not listed above will be spread onto the underlying
DatePickerMonth
element.
interface UpdateMonthParams {
prev: () => void;
next: () => void;
}
children: React.ReactNode;
updateMonth: ({ prev, next }: UpdateMonthParams) => void;
Any props not listed above will be spread onto the underlying
DatePickerButton
element.
interface RenderDayLabelParams {
date: Date;
isSelected: boolean;
isSelectable: boolean;
}
renderDayLabel?: ({ date, isSelected, isSelectable }: RenderDayLabelParams) => string;
renderDayContent?: (date: Date) => React.ReactNode;
Any props not listed above will be spread onto the underlying
DatePickerTable
element.
react-datepicker
doesn't provide any default styling; you're free to do what you want and use what you want.
// Example using CSS Modules
import * as styles from './styles';
<DatePicker
className={styles.wrapper}
onSelect={date => console.log(date)}
>
<DatePickerInput className={styles.input} />
<DatePickerCalendar>
<DatePickerMonth className={styles.selectedMonth} />
<DatePickerButton
className={styles.button}
updateMonth={({ prev }) => prev()}
>
Prev Month
</DatePickerButton>
<DatePickerButton
className={styles.button}
updateMonth={({ next }) => next()}
>
Next Month
</DatePickerButton>
<DatePickerTable className={styles.table} />
</DatePickerCalendar>
</DatePicker>