Simple Year Calendar

Creating a Year Calendar component in React: A Step-by-Step Guide

Create a react app and add these dependencies.

1 yarn add date-fns

I'm utilizing Tailwind CSS, but feel free to use it as well or create your own styles, styled components, etc.

Lets get the dates in a year.

Each year calendar consists of seven days per week. 7 rows in year calendar.

Let's explore how to retrieve all the dates for a specified year using date-fns.

1//array to hold all the dates
2const dates = [];
3//Get the start day of the month
4const startCal = startOfWeek(startOfYear(date));
5
6//add 1 year to the start date to get the end of this calendar view
7const endCal = addYears(startOfYear(date), 1);
8
9let theDate = startCal;
10do {
11 dates.push(theDate);
12 //add a day
13 theDate = addDays(theDate, 1);
14} while (theDate < endCal); //check if theDate is within this calendar

Our main Year Calendar component

Lets design our main year calendar component. I am using tailwind css, feel free to use it ir create your own styles.

1<div className='flex justify-center border-solid border-red-500 border-2 p-2 rounded-xl'>
2 <div className='flex flex-wrap h-[336px]'>Our Body goes here</div>
3</div>
Our Body goes here

Lets build the body

Now lets create a parent div with a flex layout which wraps and has a height of 48 * 7 cards = 336px

1<div className='flex flex-col flex-wrap items-center h-[336px]'>
2 {calDates.map((d, i) => (
3 <div
4 className={`cursor-pointer border-2 border-base-400 border-solid p-1 w-6 h-6 text-center
5 hover:bg-red-400
6 ${d.date.getMonth() % 2 === 0 ? 'bg-red-50' : 'bg-red-200'} `}
7 key={i}
8 >
9 {d.date.getDate()}
10 </div>
11 ))}
12</div>

Putting it all together

1import { useMemo, useState } from 'react';
2import { startOfWeek, addDays, startOfYear, addYears } from 'date-fns';
3
4const today = new Date();
5
6export default function YearCalendar() {
7 const [date, setDate] = useState(today);
8
9 const calDates = useMemo(() => {
10 const dates = [];
11
12 const startCal = startOfWeek(startOfYear(date));
13 const endCal = addYears(startCal, 1);
14
15 let theDate = startCal;
16
17 do {
18 dates.push({
19 date: theDate,
20 isInMonth: theDate.getMonth() === date.getMonth(),
21 });
22 theDate = addDays(theDate, 1);
23 } while (theDate < endCal);
24 return dates;
25 }, [date]);
26
27 return (
28 <div className='flex justify-center border-solid border-red-500 border-2 rounded-xl p-[4px]'>
29 <div className='overflow-y-hidden hover:overflow-y-auto '>
30 <div className='flex flex-col flex-wrap items-center h-[336px]'>
31 {calDates.map((d, i) => (
32 <div
33 className={`cursor-pointer border-2 border-base-400 border-solid p-1 w-6 h-6 text-center
34 hover:bg-red-400
35 ${d.date.getMonth() % 2 === 0 ? 'bg-red-50' : 'bg-red-200'} `}
36 key={i}
37 >
38 {d.date.getDate()}
39 </div>
40 ))}
41 </div>
42 </div>
43 </div>
44 );
45}

Demo

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

Conclusion

You can modify the above to include the month header and the weekdays.