DEV Community

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

Posted on

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

Top comments (0)