Customize Material-UI Datepicker With React


Material-UI Datepicker is a great Tool we can use as a calendar, but it is a bit confusing to work with and a bit confusing to customize so I decided to share a few things I found about it in this article. Also this is going to be a bit long 🙃. So I divide the article into three main sections.

Those who are pro in setting things up , just hop down👇 for customizing section .


Prerequisites 🤔

  • npm installed
  • npx installed
  • Node Js
  • Familiar with ReactJs/Javascript
  • Familiar with CSS

Setup 😋

Go through following steps to set up our react app and calendar component.

1
npx create-react-app custom-calendar

Run this command with cmd in an empty folder. Here “custom-calendar” is just a name I like, you can use whatever you wish.

  1. open created project with your favorite IDE (I’m using Webstrome).

  2. npm run start

In the IDE terminal run this and make sure the react project is working. If everything is fine you browser will pop up with http://localhost:3000 shows,

Empty project window
  1. Then let’s install relevant packages.

NOTE : Since date-fns latest versions have some breaking issues . I’m specifying a working combination of package versions, feel free to upgrade and try overtime.

1
2
3
npm i @material-ui/pickers@3.2.10 --save
npm install date-fns@2.16.1 --save
npm install @date-io/date-fns@1.3.13 --save

Run above three lines to install Material-UI, Material-UI pickers and date-fns. Material-UI pickers were designed to use the date management library of our choice so we can use whatever preferred library. Here I use date-fns. You can use moment, luxon or dayjs also. Make sure these three packages are in the dependencies list of your package.json.


Design 👨‍🎨

Now setting up packages is done 🥳. Then in the src folder create a js file, I’m naming it as CustomCalendar.js. Then add the following codes.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import React, {useState} from 'react';
import DateFnsUtils from "@date-io/date-fns";
import {
DatePicker,
MuiPickersUtilsProvider,
} from '@material-ui/pickers';
export default function CustomCalendar() {
const [selectedDate, handleDateChange] = useState(new Date());
return (
<div>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<DatePicker
value={selectedDate}
onChange={handleDateChange}
variant="static"
/>
</MuiPickersUtilsProvider>
</div>
);
}

This is a functional component. I’ll explain confusing lines for you.

  1. In line 8, I used react useState to keep the currently selected date as a state.
  2. In line 11, As I mentioned before, Material-UI Datepicker needs a date management library, so MuiPickersUtilsProvider provides that DateFnsUtils as utill.
  3. variant=”static” is used to keep the DatePicker open so that it can act as a Calendar.(huh 😌 that’s what we need)

Then let’s edit the App.js file as follows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import React from 'react';
import CustomCalendar from "./CustomCalendar"
import './App.css';

function App() {
return (
<div className="App" style={{
display: "grid",
placeItems: "center",
height:"100vh",
}}>
<CustomCalendar/>
</div>
);
}

export default App;

  • In line 2, import our CustomCalendar component.
  • line line 7–11, just place our calendar in the middle of our page.

Then if everything went well, hop back to your browser and refresh,

Raw calendar view

Customize 😍

Method 1

Great 🥳 , we have a working Calendar in standard theme. And you can access the selected date from the state. Let’s give it a try to do some customizations. You can learn about basic css customizations on Material-UI picker from the official documentation.

Briefly, we can override the css of DatePicker, by creating a new theme using createMuiTheme and provide it to the DatePicker using ThemeProvider.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import React, {useState} from 'react';
import DateFnsUtils from "@date-io/date-fns";
import {
DatePicker,
MuiPickersUtilsProvider,
} from '@material-ui/pickers';
import {createMuiTheme} from "@material-ui/core";
import {ThemeProvider} from "@material-ui/styles";

const materialTheme = createMuiTheme({
overrides: {
MuiPickersToolbar: {
toolbar: {
backgroundColor: "#8bc34a",
},
},
MuiPickersCalendarHeader: {
switchHeader: {
backgroundColor: "white",
color: "#1b5e20",
},
},
},
});
export default function CustomCalendar() {
const [selectedDate, handleDateChange] = useState(new Date());
return (
<div>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<ThemeProvider theme={materialTheme}>
<DatePicker
value={selectedDate}
onChange={handleDateChange}
variant="static"
></DatePicker>
</ThemeProvider>
</MuiPickersUtilsProvider>
</div>
);
}

Calendar after the customization

Method 2

There are limitations of overriding when it comes to customizing date tiles. In the following section I will show how to use the renderDay prop of DatePicker to extend our customization. Here I’m using makeStyles and Material-Ui Icons. First install those external libraries with,

1
2
npm install @material-ui/icons
npm install @material-ui/styles

renderDate prop requires a function that accepts (day: Date, selectedDate: Date, isInCurrentMonth: boolean, dayComponent: Element) and then returns Element that can be rendered as date tile. Datepicker invokes this function with each and every date shown on it.

So, for this section I’m going to mark sunny days by adding ☀ on Date tiles and change the look of tiles a little bit so you can get a better idea.

Step 1

Using makeStyles I created four css settings for four type of Date tiles which are,

  • Today tile
  • Selected date tile
  • Normal date tile
  • Days not belongs to current month

Step 2

Write a function that accepts (day: Date, selectedDate: Date, isInCurrentMonth: boolean, dayComponent: Element) and conditionally returns Element to render as one date tile.

Step 3

Give that function to the renderDate prop. Then DatePicker calls our function every time it renders a date and asks for a date tile. Our function evaluates the day and returns an appropriate date tile.

Here is the code of CustomCalendar.js,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import React, {useState} from 'react';
import DateFnsUtils from "@date-io/date-fns";
import {DatePicker, MuiPickersUtilsProvider,} from '@material-ui/pickers';
import {Paper, Grid} from "@material-ui/core";
import {createMuiTheme} from "@material-ui/core";
import {ThemeProvider} from "@material-ui/styles";
import {makeStyles} from "@material-ui/core/styles";
import WbSunnyIcon from '@material-ui/icons/WbSunny';

const materialTheme = createMuiTheme({
overrides: {
MuiPickersToolbar: {
toolbar: {backgroundColor: "#8bc34a",},
},
MuiPickersCalendarHeader: {
switchHeader: {
backgroundColor: "white",
color: "#1b5e20",
},},},});

export const styles = makeStyles(() => ({ //define CSS for different date types
notInThisMonthDayPaper: {
width: "35px",
height: "35px",
backgroundColor: "#eeeeee",
margin: "3px",
boxShadow: "none",
borderRadius: 0,
padding: "1px",
},
normalDayPaper: {
width: "35px",
height: "35px",
backgroundColor: "#e8f5e9",
margin: "3px",
boxShadow: "none",
borderRadius: 0,
padding: "1px",
cursor: "pointer",
},
selectedDayPaper: {
width: "31px",
height: "31px",
backgroundColor: "#f9fbe7",
margin: "3px",
boxShadow: "none",
borderRadius: 0,
borderStyle: "solid",
borderWidth: "2px",
borderColor: "lime",
padding: "1px",
cursor: "pointer",
},
todayPaper: {
width: "35px",
height: "35px",
backgroundColor: "lightGreen",
margin: "3px",
boxShadow: "none",
borderRadius: 0,
padding: "1px",
cursor: "pointer",
color: " white",
},}));
export default function CustomCalendar() {
const [selectedDate, handleDateChange] = useState(new Date());
const classes = styles(); // import those CSS
const today = new Date(); // just Date object of today
const sunnyDays = [1, 6, 10, 24, 15] // array of sunny days 1st,6th etc

function getDayElement(day, selectedDate, isInCurrentMonth, dayComponent) {
//generate boolean
const isSunny = sunnyDays.includes(day.getDate());
const isSelected = day.getDate() === selectedDate.getDate();
const isToday = day.getDate() === today.getDate() && day.getMonth() === today.getMonth();

let dateTile
if (isInCurrentMonth) { //conditionally return appropriate Element of date tile.
if (isSunny) {
dateTile = (
<Paper className={isSelected ? classes.selectedDayPaper : isToday ? classes.todayPaper : classes.normalDayPaper}>
<Grid item><WbSunnyIcon style={{color: "orange"}}/></Grid>
<Grid item>
{day.getDate()}
</Grid>
</Paper>)
} else {
dateTile = (
<Paper className={isSelected ? classes.selectedDayPaper : isToday ? classes.todayPaper : classes.normalDayPaper}>
<Grid item><br/></Grid>
<Grid item> {day.getDate()}</Grid>
</Paper>)
}

} else {
dateTile = (<Paper className={classes.notInThisMonthDayPaper}>
<Grid item><br/></Grid>
<Grid item style={{color: "lightGrey"}}>
{day.getDate()}
</Grid>
</Paper>)
}
return dateTile
}
return (
<div>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<ThemeProvider theme={materialTheme}>
<DatePicker
value={selectedDate}
onChange={handleDateChange}
variant="static"
// using our function
renderDay={(day, selectedDate, isInCurrentMonth, dayComponent) => getDayElement(day, selectedDate, isInCurrentMonth, dayComponent)}
/>

</ThemeProvider>
</MuiPickersUtilsProvider>
</div>
);}

Here, this is just a square tile that contains a date. I just use Paper and Grid to build it because they are really handy when making layouts. Similar to class in HTML/CSS in React we can use className to apply CSS settings.

So hope you learn something from this article. Using these two methods you can customize Material-UI DatePicker to match with your needs and theme.

Final result

🥰 You can use this idea to make your own designs. happy coding!!!
You can get all codes from Git Repo.

React Material Date Picker

React Material Date Picker

Github repository for all the code

github.com