Building a React GitHub Heatmap Contributions

JavaScriptJavaScriptIntermediate
Practice Now

Introduction

This project will lead you through creating a heatmap calendar in React, resembling GitHub's contribution graph. This kind of calendar can be a compelling way to visualize activity data over time, with the intensity of color indicating the level of activity on a given day. By the end of this project, you will have a clear understanding of how to integrate and use a calendar heatmap in a React application.

๐Ÿ‘€ Preview

Install Necessary Dependencies

The foundation of our heatmap calendar is a new React application.

Functionality:

  • Install project dependencies.
  • Install the react-calendar-heatmap library for the heatmap.
  • Install date-fns for easy date manipulation.

To install project dependencies, use the following command๏ผš

cd github-heatmap-calendar
npm install

To add the calendar heatmap functionality, we need to install a React-specific library, along with a date utility library.(The library is already included in the project and does not need to be installed.)

npm install react-calendar-heatmap date-fns

Create the Heatmap Component Shell

We'll start by creating the basic structure of our heatmap component without any functionality.

Functionality:

  • Create a new file for the heatmap component.
  • Define the functional component with placeholder content.

Code:

// src/GitHubCalendar.js
import React from "react";

const GitHubCalendar = () => {
  return (
    <div>
      {/* Placeholder for the heatmap */}
      <div>Heatmap will go here</div>
    </div>
  );
};

export default GitHubCalendar;
โœจ Check Solution and Practice

Add State for Filtering

Before we populate our heatmap, let's add some state to manage the filtering of data based on user interaction.

Functionality:

  • Import the useState hook.
  • Initialize the colorFilter state variable.

Code:

// src/GitHubCalendar.js
import React, { useState } from "react";

const GitHubCalendar = () => {
  const [colorFilter, setColorFilter] = useState(null);

  return (
    <div>
      {/* Placeholder for the heatmap */}
      <div>Heatmap will go here</div>
    </div>
  );
};

export default GitHubCalendar;
โœจ Check Solution and Practice

Generate Dummy Data

Generate dummy data to simulate activity. We will replace this with actual data in a real-world application.

Functionality:

  • Utilize date-fns to create a date range.
  • Populate an array with dummy data for each day.

Code:

// src/GitHubCalendar.js
import { subYears, isBefore, format } from "date-fns";

// Add inside the GitHubCalendar component
const startDate = subYears(new Date(), 1);
const endDate = new Date();
const values = [];
let currentDate = startDate;

while (isBefore(currentDate, endDate)) {
  values.push({
    date: format(currentDate, "yyyy-MM-dd"),
    count: Math.floor(Math.random() * 5)
  });
  currentDate = new Date(currentDate.setDate(currentDate.getDate() + 1));
}
โœจ Check Solution and Practice

Render the Calendar Heatmap

Now we'll include the CalendarHeatmap component and pass our dummy data to it.

Functionality:

  • Render the heatmap with data.
  • Define a color scale based on the count.

Code:

// src/GitHubCalendar.js
import CalendarHeatmap from "react-calendar-heatmap";
import "react-calendar-heatmap/dist/styles.css";

// Add inside the GitHubCalendar component's return statement
<CalendarHeatmap
  startDate={startDate}
  endDate={endDate}
  values={values}
  classForValue={(value) => {
    if (!value || value.count === 0) {
      return "color-empty";
    }
    return `color-scale-${value.count}`;
  }}
  showWeekdayLabels={true}
/>;
โœจ Check Solution and Practice

Implement Filtering Logic

Create buttons for each level of activity that will filter the heatmap when clicked.

Functionality:

  • Add buttons that set the colorFilter state.
  • Filter the heatmap data based on the selected filter.

Code:

// src/GitHubCalendar.js
// Add below the CalendarHeatmap component in the return statement
<div className="filter-bar">
  {Array.from({ length: 5 }, (_, i) => (
    <button
      key={i}
      className={`filter-btn color-scale-${i}`}
      onClick={() => setColorFilter(colorFilter === i ? null : i)}
    >
      Filter {i}
    </button>
  ))}
</div>
โœจ Check Solution and Practice

Style the Component

Define the CSS for the heatmap and filter buttons to visually communicate the data.

Functionality:

  • Add CSS rules for the heatmap colors and button styling.

Code:

/* src/App.css */
/* Add your CSS rules here */
.color-empty {
  fill: #ebedf0; /* No contributions - white color */
}
.color-scale-0 {
  fill: #ebedf0; /* Lightest green - Change this to your lightest green */
}
.color-scale-1 {
  fill: #9be9a8; /* Light green */
}
.color-scale-2 {
  fill: #40c463; /* Medium green */
}
.color-scale-3 {
  fill: #30a14e; /* Dark green */
}
.color-scale-4 {
  fill: #216e39; /* Darkest green */
}

.filter-bar {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

.filter-btn {
  background: none;
  border: 2px solid transparent;
  margin: 0 5px;
  padding: 5px 10px;
  cursor: pointer;
  transition:
    background-color 0.3s,
    border-color 0.3s;
}

/* Apply the same colors to the filter buttons */
.filter-btn.color-scale-0 {
  border-color: #ebedf0;
}
.filter-btn.color-scale-1 {
  border-color: #9be9a8;
}
.filter-btn.color-scale-2 {
  border-color: #40c463;
}
.filter-btn.color-scale-3 {
  border-color: #30a14e;
}
.filter-btn.color-scale-4 {
  border-color: #216e39;
}

.filter-btn:hover,
.filter-btn:focus {
  background-color: #ddd;
}

.reset {
  border-color: #000; /* Reset button border color */
}

/* Highlight the active filter */
.filter-btn.active {
  border-color: #666; /* Active button border color */
  font-weight: bold;
}

Refer to previous CSS examples for guidance on setting up the color scales and button styles.

โœจ Check Solution and Practice

Assemble the Application

Integrate the heatmap component into your main application file.

Functionality:

  • Import the GitHubCalendar component into App.js.
  • Render the GitHubCalendar component in the application.

Code:

// src/App.js
import React from "react";
import "./App.css";
import GitHubCalendar from "./GitHubCalendar";

function App() {
  return (
    <div className="App">
      <GitHubCalendar />
    </div>
  );
}

export default App;
โœจ Check Solution and Practice

Launch the Application

With all the pieces in place, it's time to see your heatmap calendar in action.

Functionality:

  • Run the application and view the heatmap calendar.

Commands:

npm start

This will compile the React application and open it in your default web browser at 8080.

Summary

Congratulations! You have just created a React application that includes a heatmap calendar similar to GitHub's contribution graph. Starting with the project initialization, you installed necessary libraries, created a heatmap component, implemented filtering functionality, and styled the component. This project provided a step-by-step approach to building a complex UI component in React, which can be adapted to display various types of time-series data or user activity.

Other JavaScript Tutorials you may like