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