npm.io
0.1.7 • Published 6d ago

@rsalianto/git-heatmap-vue

Licence
MIT
Version
0.1.7
Deps
1
Size
32 kB
Vulns
0
Weekly
0

@rsalianto/git-heatmap-vue

Vue 3 component and composable for displaying GitHub/GitLab contribution heatmaps.

git-heatmap preview

Part of the @rsalianto/git-heatmap family — available for React, Vue, Angular, Vanilla JS, and Next.js.

Installation

npm install @rsalianto/git-heatmap-vue

@rsalianto/git-heatmap-core is not required separately — buildHeatmapData, buildHeatmapDataForYear, and normalizeManual are re-exported directly from this package.


Usage

Register globally (plugin)
// main.ts
import { createApp } from "vue";
import { GitHeatmapPlugin } from "@rsalianto/git-heatmap-vue";
import App from "./App.vue";

createApp(App).use(GitHeatmapPlugin).mount("#app");
<template>
  <GitHeatmap api-url="/api/contributions" @day-click="onDayClick" />
</template>
Import locally
<script setup lang="ts">
import { GitHeatmap } from "@rsalianto/git-heatmap-vue";

function onDayClick(day: { date: string; count: number }) {
  console.log(day);
}
</script>

<template>
  <GitHeatmap api-url="/api/contributions" @day-click="onDayClick" />
</template>
Pass data directly
<script setup lang="ts">
import { GitHeatmap, buildHeatmapData } from "@rsalianto/git-heatmap-vue";

const data = buildHeatmapData([
  { date: "2025-06-01", count: 4 },
  { date: "2025-06-15", count: 9 },
]);
</script>

<template>
  <GitHeatmap :data="data" />
</template>
Display a specific year
<script setup lang="ts">
import { GitHeatmap, buildHeatmapDataForYear } from "@rsalianto/git-heatmap-vue";

const data = buildHeatmapDataForYear(allEntries, 2024);
</script>

<template>
  <GitHeatmap :data="data" />
</template>
Server-side data (Nuxt)
// server/api/contributions.get.ts
import { fetchGitHubContributions } from "@rsalianto/git-heatmap-core/fetchers/github";

export default defineEventHandler(async () => {
  return fetchGitHubContributions({
    username: "your-username",
    token: process.env.GITHUB_TOKEN!,
  });
});
<script setup>
const { data } = await useFetch("/api/contributions");
</script>
<template>
  <GitHeatmap :data="data" />
</template>

Props

Prop Type Default Description
data HeatmapData Pre-fetched data — skips internal fetching
apiUrl string Endpoint returning HeatmapData JSON
fetchData () => Promise<HeatmapData> Custom async data resolver
levels LevelConfig[] DEFAULT_LEVELS Color thresholds (5 levels)
cellSize number 10 Cell width/height in px
cellGap number 3 Gap between cells in px
cellRadius number 2 Cell border radius in px
showTotal boolean true Show "N contributions in the last year"
showLegend boolean true Show Less / More legend
showMonthLabels boolean true Show month labels above the grid
showDayLabels boolean true Show Mon / Wed / Fri labels
theme Partial<HeatmapTheme> Override CSS variable defaults via props
label string "Contribution heatmap" aria-label for the grid

Events

Event Payload Description
day-click HeatmapDay Emitted when a cell is clicked

HeatmapData shape

This is the format your apiUrl endpoint must return:

{
  "totalContributions": 312,
  "source": "github",
  "weeks": [
    {
      "days": [
        { "date": "2025-01-05", "count": 0,  "level": 0 },
        { "date": "2025-01-06", "count": 3,  "level": 1 },
        { "date": "2025-01-07", "count": 8,  "level": 2 },
        { "date": "2025-01-08", "count": 14, "level": 3 },
        { "date": "2025-01-09", "count": 22, "level": 4 },
        { "date": "2025-01-10", "count": 1,  "level": 1 },
        { "date": "2025-01-11", "count": 0,  "level": 0 }
      ]
    }
  ]
}

Theming

Via theme prop
<GitHeatmap
  api-url="/api/contributions"
  :theme="{
    colorL0: '#161b22',
    colorL1: '#0e4429',
    colorL2: '#006d32',
    colorL3: '#26a641',
    colorL4: '#39d353',
    textColor: 'rgba(255,255,255,0.5)',
    tooltipBg: '#1c2128',
  }"
/>
Via CSS variables
/* Dark (default) */
.heatmap-wrapper {
  --ghm-color-l0: rgba(255,255,255,0.08);
  --ghm-color-l1: #1c3d06;
  --ghm-color-l2: #3a7510;
  --ghm-color-l3: #6ab81e;
  --ghm-color-l4: #aafd35;
  --ghm-text: rgba(255,255,255,0.5);
  --ghm-tooltip-bg: #1c2128;
  --ghm-tooltip-border: rgba(255,255,255,0.1);
  --ghm-tooltip-text: rgba(255,255,255,0.75);
  --ghm-font: inherit;
  --ghm-fs: 11px;
  --ghm-selected: rgba(255,255,255,0.7);
  --ghm-skeleton-opacity: 0.4;
}

/* Light theme */
.heatmap-wrapper {
  --ghm-color-l0: #ebedf0;
  --ghm-color-l1: #9be9a8;
  --ghm-color-l2: #40c463;
  --ghm-color-l3: #30a14e;
  --ghm-color-l4: #216e39;
  --ghm-text: rgba(0,0,0,0.5);
  --ghm-tooltip-bg: #fff;
  --ghm-tooltip-border: #d0d7de;
  --ghm-tooltip-text: #24292f;
  --ghm-selected: rgba(0,0,0,0.4);
}

useHeatmapData composable

import { useHeatmapData } from "@rsalianto/git-heatmap-vue";

const { data, status, error } = useHeatmapData({ apiUrl: "/api/contributions" });
// status: Ref<"idle" | "loading" | "success" | "error">

Keywords