DEV Community

Cover image for GitHub like Contribution HeatMap in JS
Ajay Krupal K
Ajay Krupal K

Posted on

2

GitHub like Contribution HeatMap in JS

Have you ever wondered how you could replicate the GitHub contribution chart? Most of us have, so here is how you also could do it.

We will be using a library called cal-heatmap

You can install the library with npm install cal-heatmap and then import the library into your application:



import CalHeatmap from 'cal-heatmap';

// Optionally import the CSS
import 'cal-heatmap/cal-heatmap.css';


Enter fullscreen mode Exit fullscreen mode

Insert <div id="cal-heatmap"></div> to render the heatmap and instantiate the paint function:



const cal = new CalHeatmap();
cal.paint({
   itemSelector: '#cal-heatmap',
});


Enter fullscreen mode Exit fullscreen mode

Define the domain and sub-domain, where the domain is main time unit and the sub-domain is the sub-time unit. In this case we will have domain as month and sub-domain as ghDay so that there are no gaps in the charts



cal.paint({
   itemSelector: '#cal-heatmap',
   domain: {
      type: 'month',
      gutter: 4,
      label: { text: 'MMM', textAlign: 'start', position: 'top' },
    },
    subDomain: { type: 'ghDay', radius: 2, width: 11, height: 11, gutter: 4 },
});


Enter fullscreen mode Exit fullscreen mode

The gutter defines the space between each domain or sub-domain i.e. each month or day in our case.

The date option defines the start date of the calendar and the range option defines the number of domains to show which is 12 in our case for the number of months.



cal.paint({
   itemSelector: '#cal-heatmap',
   domain: {
      type: 'month',
      gutter: 4,
      label: { text: 'MMM', textAlign: 'start', position: 'top' },
    },
    subDomain: { type: 'ghDay', radius: 2, width: 11, height: 11, gutter: 4 },
    date: { start: new Date('2012-01-01') },
    range: 12,
});


Enter fullscreen mode Exit fullscreen mode

Now let's add the data from GitHub using GraphQL where the userName is your GitHub's username



query($userName:String!) { 
  user(login: $userName){
    contributionsCollection {
      contributionCalendar {
        totalContributions
        weeks {
          contributionDays {
            contributionCount
            date
          }
        }
      }
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

The response from the GraphQL query will be used as the source of the data



cal.paint({
   itemSelector: '#cal-heatmap',
   domain: {
      type: 'month',
      gutter: 4,
      label: { text: 'MMM', textAlign: 'start', position: 'top' },
    },
    subDomain: { type: 'ghDay', radius: 2, width: 11, height: 11, gutter: 4 },
    date: { start: new Date('2012-01-01') },
    range: 12,
    data: {
       source: response,
       x: 'date',
       y: 'contributionCount',
       defaultValue: 0
    },
});


Enter fullscreen mode Exit fullscreen mode

We will finally define how the heatmap looks with the scale property and add a tooltip and calendar label plugin.



cal.paint({
   itemSelector: '#cal-heatmap',
   domain: {
      type: 'month',
      gutter: 4,
      label: { text: 'MMM', textAlign: 'start', position: 'top' },
    },
    subDomain: { type: 'ghDay', radius: 2, width: 11, height: 11, gutter: 4 },
    date: { start: new Date('2012-01-01') },
    range: 12,
    data: {
       source: response,
       x: 'date',
       y: 'contributionCount',
       defaultValue: 0
    },
    scale: {
      color: {
        type: 'threshold',
        range: ['#14432a', '#166b34', '#37a446', '#4dd05a'],
        domain: [10, 20, 30],
      },
    },
    [
    [
      Tooltip,
      {
        text: function (date, value, dayjsDate) {
          return (
            (value ? value : 'No') +
            ' contributions on ' +
            dayjsDate.format('dddd, MMMM D, YYYY')
          );
        },
      },
    ],
    [
      CalendarLabel,
      {
        width: 30,
        textAlign: 'start',
        text: () => dayjs.weekdaysShort().map((d, i) => (i % 2 == 0 ? '' : d)),
        padding: [25, 0, 0, 0],
      },
    ],
]
});


Enter fullscreen mode Exit fullscreen mode

With this now, you should be able to see a beautiful heatmap of your GitHub contributions.

Heatmap

Follow me on X(formerly Twitter) for more tech stuff

SurveyJS custom survey software

Simplify data collection in your JS app with a fully integrated form management platform. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more. Integrates with any backend system, giving you full control over your data and no user limits.

Learn more

Top comments (0)

SurveyJS custom survey software

JavaScript Form Builder UI Component

Generate dynamic JSON-driven forms directly in your JavaScript app (Angular, React, Vue.js, jQuery) with a fully customizable drag-and-drop form builder. Easily integrate with any backend system and retain full ownership over your data, with no user or form submission limits.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay