React Nice Dates

A responsive, touch-friendly, and modular date picker library.

Overview

React Nice Dates is composed of a set of components and utilities with different levels of abstraction that you can use to build your own date pickers.

At the top level, you have DatePicker and DateRangePicker . These are slightly-opinionated components that should cover the most common use-cases. They allow displaying date inputs with a calendar popover below. They make no assumptions about how your inputs should look. Instead, they provide all the necessary props so you can render them yourself.

Here’s the most basic example using the DatePicker component:

import React , { useState } from 'react' import { enGB } from 'date-fns/locale' import { DatePicker } from 'react-nice-dates' import 'react-nice-dates/build/style.css' function DatePickerExample ( ) { const [ date , setDate ] = useState ( ) return ( < DatePicker date = { date } onDateChange = { setDate } locale = { enGB } > { ( { inputProps , focused } ) => ( < input className = { 'input' + ( focused ? ' -focused' : '' ) } { ... inputProps } /> ) } </ DatePicker > ) }

Hint: If you are using a touch device, you can also change the current month by dragging the calendar grid up or down.

Here’s a more complete example, this time using the DateRangePicker component:

import React , { useState } from 'react' import { enGB } from 'date-fns/locale' import { DateRangePicker , START_DATE , END_DATE } from 'react-nice-dates' import 'react-nice-dates/build/style.css' function DateRangePickerExample ( ) { const [ startDate , setStartDate ] = useState ( ) const [ endDate , setEndDate ] = useState ( ) return ( < DateRangePicker startDate = { startDate } endDate = { endDate } onStartDateChange = { setStartDate } onEndDateChange = { setEndDate } minimumDate = { new Date ( ) } minimumLength = { 1 } format = ' dd MMM yyyy ' locale = { enGB } > { ( { startDateInputProps , endDateInputProps , focus } ) => ( < div className = ' date-range ' > < input className = { 'input' + ( focus === START_DATE ? ' -focused' : '' ) } { ... startDateInputProps } placeholder = ' Start date ' /> < span className = ' date-range_arrow ' /> < input className = { 'input' + ( focus === END_DATE ? ' -focused' : '' ) } { ... endDateInputProps } placeholder = ' End date ' /> </ div > ) } </ DateRangePicker > ) }

Customizing how the calendar appears

Next, you have DatePickerCalendar and DateRangePickerCalendar , the calendar-only date picker components (used by DatePicker and DateRangePicker ). Use these if you want to display the calendars inline or implement your own popover component, for example.

DatePickerCalendar example:

Selected date: none. import React , { useState } from 'react' import { format } from 'date-fns' import { enGB } from 'date-fns/locale' import { DatePickerCalendar } from 'react-nice-dates' import 'react-nice-dates/build/style.css' function DatePickerCalendarExample ( ) { const [ date , setDate ] = useState ( ) return ( < div > < p > Selected date : { date ? format ( date , 'dd MMM yyyy' , { locale : enGB } ) : 'none' } . </ p > < DatePickerCalendar date = { date } onDateChange = { setDate } locale = { enGB } /> </ div > ) }

DateRangePickerCalendar example:

Selected start date: none. Selected end date: none. Currently selecting: startDate. import React , { useState } from 'react' import { format } from 'date-fns' import { enGB } from 'date-fns/locale' import { DateRangePickerCalendar , START_DATE } from 'react-nice-dates' import 'react-nice-dates/build/style.css' export default function DateRangePickerCalendarExample ( ) { const [ startDate , setStartDate ] = useState ( ) const [ endDate , setEndDate ] = useState ( ) const [ focus , setFocus ] = useState ( START_DATE ) const handleFocusChange = newFocus => { setFocus ( newFocus || START_DATE ) } return ( < div > < p > Selected start date : { startDate ? format ( startDate , 'dd MMM yyyy' , { locale : enGB } ) : 'none' } . </ p > < p > Selected end date : { endDate ? format ( endDate , 'dd MMM yyyy' , { locale : enGB } ) : 'none' } . </ p > < p > Currently selecting : { focus } . </ p > < DateRangePickerCalendar startDate = { startDate } endDate = { endDate } focus = { focus } onStartDateChange = { setStartDate } onEndDateChange = { setEndDate } onFocusChange = { handleFocusChange } locale = { enGB } /> </ div > ) }

Customizing days

Modifiers define what CSS classes are applied to each calendar day. All the components accept a modifiers prop—an object where each key corresponds to the modifier name, and each value corresponds to a function that receives a date parameter and must return a boolean determining whether that modifier class should apply to that particular day.

The default modifiers are disabled , selected , and today . You can also create your own modifiers by passing a modifiersClassNames which will be matched to the modifiers object.

import React , { useState } from 'react' import { getDay } from 'date-fns' import { enGB } from 'date-fns/locale' import { DatePickerCalendar } from 'react-nice-dates' import 'react-nice-dates/build/style.css' const modifiers = { disabled : date => getDay ( date ) === 6 , highlight : date => getDay ( date ) === 2 } const modifiersClassNames = { highlight : '-highlight' } export default function ModifiersExample ( ) { const [ date , setDate ] = useState ( ) return ( < DatePickerCalendar date = { date } onDateChange = { setDate } locale = { enGB } modifiers = { modifiers } modifiersClassNames = { modifiersClassNames } /> ) }

Implementing your own date-picking behavior

If you need to implement a date-picking behavior not covered by the previous components, you can use the Calendar component directly ( DatePickerCalendar and DateRangePickerCalendar are themselves wrappers around this component). It accepts callbacks for when a day is clicked or hovered, which you can then use to create modifiers to control which days are selected.

import React , { useState } from 'react' import { isSameDay } from 'date-fns' import { enGB } from 'date-fns/locale' import { Calendar } from 'react-nice-dates' import 'react-nice-dates/build/style.css' export default function CalendarExample ( ) { const [ selectedDates , setSelectedDates ] = useState ( [ ] ) const modifiers = { selected : date => selectedDates . some ( selectedDate => isSameDay ( selectedDate , date ) ) } const handleDayClick = date => { setSelectedDates ( [ ... selectedDates , date ] ) } return ( < Calendar onDayClick = { handleDayClick } modifiers = { modifiers } locale = { enGB } /> ) }

Parsing text inputs

You can also use the useDateInput hook if you want to have the same date-parsing functionality on text inputs in your custom implementation.

Here’s an example using it on a standalone input:

The selected date is Set today import React , { useState } from 'react' import { format } from 'date-fns' import { enGB } from 'date-fns/locale' import { useDateInput } from 'react-nice-dates' export default function StandaloneInputExample ( ) { const [ date , setDate ] = useState ( ) const inputProps = useDateInput ( { date , format : 'yyyy-MM-dd' , locale : enGB , onDateChange : setDate } ) const handleReset = ( ) => { setDate ( new Date ( ) ) } return ( < div > < p > The selected date is { date && format ( date , 'dd MMM yyyy' , { locale : enGB } ) } </ p > < button onClick = { handleReset } > Set today </ button > < input className = ' input ' { ... inputProps } /> </ div > ) }

And here it is paired with DatePickerCalendar :

The selected date is import React , { useState } from 'react' import { format } from 'date-fns' import { enGB } from 'date-fns/locale' import { DatePickerCalendar , useDateInput } from 'react-nice-dates' import 'react-nice-dates/build/style.css' export default function DatePickerCalendarWithInputExample ( ) { const [ date , setDate ] = useState ( ) const inputProps = useDateInput ( { date , format : 'yyyy-MM-dd' , locale : enGB , onDateChange : setDate } ) return ( < div > < p > The selected date is { date && format ( date , 'dd MMM yyyy' , { locale : enGB } ) } </ p > < input className = ' input ' { ... inputProps } /> < DatePickerCalendar date = { date } onDateChange = { setDate } locale = { enGB } /> </ div > ) }

Time-picking

While there’s no custom time-picking user interface, you can use an input format that includes the time, and the selected time will get carried over when the selected date changes.

import React , { useState } from 'react' import { enGB } from 'date-fns/locale' import { DatePicker } from 'react-nice-dates' import 'react-nice-dates/build/style.css' function DatePickerWithTimeExample ( ) { const [ date , setDate ] = useState ( new Date ( 2020 , 1 , 24 , 18 , 15 ) ) return ( < DatePicker date = { date } onDateChange = { setDate } locale = { enGB } format = ' dd/MM/yyyy HH:mm ' > { ( { inputProps , focused } ) => < input className = { 'input' + ( focused ? ' -focused' : '' ) } { ... inputProps } /> } </ DatePicker > ) }

You can also use separate input for the time of the date, using the useDateInput hook.

import React , { useState } from 'react' import { enGB } from 'date-fns/locale' import { DatePicker } from 'react-nice-dates' import 'react-nice-dates/build/style.css' function DatePickerWithTimeInputExample ( ) { const [ date , setDate ] = useState ( new Date ( 2020 , 1 , 24 , 18 , 15 ) ) const timeInputProps = useDateInput ( { date , format : 'HH:mm' , locale : enGB , onDateChange : setDate } ) return ( < div style = { { display : 'flex' } } > < DatePicker date = { date } onDateChange = { setDate } locale = { enGB } format = ' dd/MM/yyyy ' > { ( { inputProps , focused } ) => ( < input className = { 'input' + ( focused ? ' -focused' : '' ) } style = { { width : 150 } } { ... inputProps } /> ) } </ DatePicker > < input className = ' input ' style = { { marginLeft : 16 , width : 80 } } { ... timeInputProps } /> </ div > ) }

Localization

As you might have noticed, React Nice Dates relies of the awesome date-fns library as a peer dependency. All components require a locale prop, which must be a date-fns locale object of your desired language.

US English:

Spanish: import React , { useState } from 'react' import { enUS , es } from 'date-fns/locale' import { DatePicker } from 'react-nice-dates' import 'react-nice-dates/build/style.css' export default function LocalesExample ( ) { const [ date , setDate ] = useState ( ) return ( < div > < p > US English : </ p > < DatePicker date = { date } onDateChange = { setDate } locale = { enUS } > { ( { inputProps , focused } ) => ( < input className = { 'input' + ( focused ? ' -focused' : '' ) } { ... inputProps } /> ) } </ DatePicker > < p > Spanish : </ p > < DatePicker date = { date } onDateChange = { setDate } locale = { es } format = ' dd/MM/yyyy ' > { ( { inputProps , focused } ) => ( < input className = { 'input' + ( focused ? ' -focused' : '' ) } { ... inputProps } placeholder = ' DD/MM/YYYY ' /> ) } </ DatePicker > </ div > ) }

Installation

1. Add the react-nice-dates and date-fns packages to your dependencies.

With NPM:

npm install react-nice-dates date-fns --save

Or with Yarn:

yarn add react-nice-dates date-fns

2. Import the desired components, a date-fns locale object of your language, and the CSS:

import { enGB } from 'date-fns/locale' import { DatePickerCalendar } from 'react-nice-dates' import 'react-nice-dates/build/style.css' < DatePickerCalendar locale = { enGB } />

Style customization

You can use and override the compiled CSS on your project:

.nice-dates-navigation , .nice-dates-day { color : #111 ; } .nice-dates-popover { box-shadow : none ; border : 1 px solid #ddd ; border-radius : 2 px ; max-width : 480 px ; transition : none ; }

Or, if you’re using SASS, import the original SASS file for easier customization:

$nice-dates-color-gray-dark : #333 ; $nice-dates-color-gray : #999 ; $nice-dates-color-gray-light : #ddd ; $nice-dates-color-accent : $nice-dates-color-gray-dark ; $nice-dates-font-size-small : 12 px ; $nice-dates-font-size-base : 14 px ; $nice-dates-font-size-big : 16 px ; @import 'react-nice-dates/src/style.scss' ;

API Reference

DatePicker props

children : func . isRequired , locale : object . isRequired , date : instanceOf ( Date ) , onDateChange : func , format : string , minimumDate : instanceOf ( Date ) , maximumDate : instanceOf ( Date ) , modifiers : objectOf ( func ) , modifiersClassNames : objectOf ( string ) , weekdayFormat : string

inputProps properties:

onBlur , onChange , onFocus , placeholder , readOnly , ref , type , value

DateRangePicker props

children : func . isRequired , locale : object . isRequired , startDate : instanceOf ( Date ) , endDate : instanceOf ( Date ) , onStartDateChange : func , onEndDateChange : func , format : string , minimumDate : instanceOf ( Date ) , maximumDate : instanceOf ( Date ) , minimumLength : number , maximumLength : number , modifiers : objectOf ( func ) , modifiersClassNames : objectOf ( string ) , weekdayFormat : string

startDateInputProps and endDateInputProps properties:

onBlur , onChange , onFocus , placeholder , readOnly , ref , type , value

DatePickerCalendar props

locale : object . isRequired , date : instanceOf ( Date ) , month : instanceOf ( Date ) , onDateChange : func , onMonthChange : func , minimumDate : instanceOf ( Date ) , maximumDate : instanceOf ( Date ) , modifiers : objectOf ( func ) , modifiersClassNames : objectOf ( string ) , weekdayFormat : string

DateRangePickerCalendar props

locale : object . isRequired , startDate : instanceOf ( Date ) , endDate : instanceOf ( Date ) , focus : oneOf ( [ START_DATE , END_DATE ] ) , month : instanceOf ( Date ) , onStartDateChange : func . isRequired , onEndDateChange : func . isRequired , onFocusChange : func . isRequired , onMonthChange : func , minimumDate : instanceOf ( Date ) , maximumDate : instanceOf ( Date ) , minimumLength : number , maximumLength : number , modifiers : objectOf ( func ) , modifiersClassNames : objectOf ( string ) , weekdayFormat : string

Calendar props

locale : object . isRequired , minimumDate : instanceOf ( Date ) , maximumDate : instanceOf ( Date ) , modifiers : objectOf ( func ) , modifiersClassNames : objectOf ( string ) , month : instanceOf ( Date ) , onMonthChange : func , onDayHover : func , onDayClick : func , weekdayFormat : string

useDateInput