Data Display dataheatmapactivitygithubmatrix
Activity Heatmap Grid
GitHub-styled commit/activity frequency matrix visualizing contribution density across days and weeks.
Preview
Contribution Activity
1,428 events in the last 4 months Less More
JulAugSepOct
Usage
Copy the full block below to use this component with its imports.
astro
---
import { ActivityHeatmapGrid } from 'astro-component-kit';
---
<ActivityHeatmapGrid title="Contribution Activity" weeks={16} /> ---
import { ActivityHeatmapGrid } from 'astro-component-kit';
---
<ActivityHeatmapGrid title="Contribution Activity" weeks={16} /> Manual Installation
If you are not using the npm package, create a new file src/components/lib/ActivityHeatmapGrid.astro and paste the following code:
astro
---
/**
* ActivityHeatmapGrid — GitHub-style activity contribution matrix with intensity color levels and month labels.
*
* @param {string} title - Section header label. Default is 'Commit Activity'.
* @param {number} totalCount - Total activity events recorded. Default is 1428.
*/
interface Props {
title?: string;
totalCount?: number;
}
const {
title = 'Contribution Activity',
totalCount = 1428,
} = Astro.props;
// Mock 16 weeks of 7 days
const weeks = Array.from({ length: 16 }, (_, w) =>
Array.from({ length: 7 }, (_, d) => {
// Generate pseudo-random intensity 0 to 4
const seed = (w * 7 + d * 13 + 5) % 17;
if (seed < 4) return 0;
if (seed < 8) return 1;
if (seed < 12) return 2;
if (seed < 15) return 3;
return 4;
})
);
const months = ['Jul', 'Aug', 'Sep', 'Oct'];
---
<div class="heatmap-card">
<div class="heatmap-card__head">
<div class="heatmap-card__title-wrap">
<h5 class="heatmap-card__title">{title}</h5>
<span class="heatmap-card__total">{totalCount.toLocaleString()} events in the last 4 months</span>
</div>
<div class="heatmap-card__legend" aria-hidden="true">
<span class="legend-text">Less</span>
<span class="cell cell--0"></span>
<span class="cell cell--1"></span>
<span class="cell cell--2"></span>
<span class="cell cell--3"></span>
<span class="cell cell--4"></span>
<span class="legend-text">More</span>
</div>
</div>
<div class="heatmap-card__matrix">
<div class="heatmap-card__months">
{months.map((m) => (
<span class="month-label">{m}</span>
))}
</div>
<div class="heatmap-card__grid">
{weeks.map((week) => (
<div class="heatmap-col">
{week.map((level) => (
<span class:list={['cell', `cell--${level}`]}></span>
))}
</div>
))}
</div>
</div>
</div>
<style>
.heatmap-card {
display: flex;
flex-direction: column;
gap: 12px;
padding: var(--sp-6, 1.5rem);
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: var(--r-xl, 20px);
width: 100%;
max-width: 480px;
font-family: var(--font-sans, system-ui, sans-serif);
}
.heatmap-card__head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
}
.heatmap-card__title {
font-size: 0.95rem;
font-weight: 700;
color: var(--c-text-1, #ffffff);
margin: 0 0 2px 0;
}
.heatmap-card__total {
font-size: 0.75rem;
color: var(--c-text-3, #737373);
}
.heatmap-card__legend {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.7rem;
color: var(--c-text-3, #737373);
}
.heatmap-card__matrix {
display: flex;
flex-direction: column;
gap: 6px;
overflow-x: auto;
padding-bottom: 4px;
}
.heatmap-card__months {
display: flex;
justify-content: space-between;
padding: 0 4px;
font-size: 0.68rem;
color: var(--c-text-3, #737373);
font-weight: 600;
}
.heatmap-card__grid {
display: flex;
gap: 4px;
}
.heatmap-col {
display: flex;
flex-direction: column;
gap: 4px;
}
.cell {
width: 12px;
height: 12px;
border-radius: 3px;
transition: transform 0.15s ease;
}
.heatmap-card__grid .cell:hover {
transform: scale(1.3);
}
.cell--0 { background: rgba(255, 255, 255, 0.05); }
.cell--1 { background: rgba(184, 134, 11, 0.25); }
.cell--2 { background: rgba(184, 134, 11, 0.55); }
.cell--3 { background: rgba(212, 160, 23, 0.85); }
.cell--4 { background: #fef3c7; box-shadow: 0 0 6px rgba(254, 243, 199, 0.6); }
</style> ---
/**
* ActivityHeatmapGrid — GitHub-style activity contribution matrix with intensity color levels and month labels.
*
* @param {string} title - Section header label. Default is 'Commit Activity'.
* @param {number} totalCount - Total activity events recorded. Default is 1428.
*/
interface Props {
title?: string;
totalCount?: number;
}
const {
title = 'Contribution Activity',
totalCount = 1428,
} = Astro.props;
// Mock 16 weeks of 7 days
const weeks = Array.from({ length: 16 }, (_, w) =>
Array.from({ length: 7 }, (_, d) => {
// Generate pseudo-random intensity 0 to 4
const seed = (w * 7 + d * 13 + 5) % 17;
if (seed < 4) return 0;
if (seed < 8) return 1;
if (seed < 12) return 2;
if (seed < 15) return 3;
return 4;
})
);
const months = ['Jul', 'Aug', 'Sep', 'Oct'];
---
<div class="heatmap-card">
<div class="heatmap-card__head">
<div class="heatmap-card__title-wrap">
<h5 class="heatmap-card__title">{title}</h5>
<span class="heatmap-card__total">{totalCount.toLocaleString()} events in the last 4 months</span>
</div>
<div class="heatmap-card__legend" aria-hidden="true">
<span class="legend-text">Less</span>
<span class="cell cell--0"></span>
<span class="cell cell--1"></span>
<span class="cell cell--2"></span>
<span class="cell cell--3"></span>
<span class="cell cell--4"></span>
<span class="legend-text">More</span>
</div>
</div>
<div class="heatmap-card__matrix">
<div class="heatmap-card__months">
{months.map((m) => (
<span class="month-label">{m}</span>
))}
</div>
<div class="heatmap-card__grid">
{weeks.map((week) => (
<div class="heatmap-col">
{week.map((level) => (
<span class:list={['cell', `cell--${level}`]}></span>
))}
</div>
))}
</div>
</div>
</div>
<style>
.heatmap-card {
display: flex;
flex-direction: column;
gap: 12px;
padding: var(--sp-6, 1.5rem);
background: rgba(255, 255, 255, 0.02);
backdrop-filter: blur(16px);
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: var(--r-xl, 20px);
width: 100%;
max-width: 480px;
font-family: var(--font-sans, system-ui, sans-serif);
}
.heatmap-card__head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 12px;
}
.heatmap-card__title {
font-size: 0.95rem;
font-weight: 700;
color: var(--c-text-1, #ffffff);
margin: 0 0 2px 0;
}
.heatmap-card__total {
font-size: 0.75rem;
color: var(--c-text-3, #737373);
}
.heatmap-card__legend {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.7rem;
color: var(--c-text-3, #737373);
}
.heatmap-card__matrix {
display: flex;
flex-direction: column;
gap: 6px;
overflow-x: auto;
padding-bottom: 4px;
}
.heatmap-card__months {
display: flex;
justify-content: space-between;
padding: 0 4px;
font-size: 0.68rem;
color: var(--c-text-3, #737373);
font-weight: 600;
}
.heatmap-card__grid {
display: flex;
gap: 4px;
}
.heatmap-col {
display: flex;
flex-direction: column;
gap: 4px;
}
.cell {
width: 12px;
height: 12px;
border-radius: 3px;
transition: transform 0.15s ease;
}
.heatmap-card__grid .cell:hover {
transform: scale(1.3);
}
.cell--0 { background: rgba(255, 255, 255, 0.05); }
.cell--1 { background: rgba(184, 134, 11, 0.25); }
.cell--2 { background: rgba(184, 134, 11, 0.55); }
.cell--3 { background: rgba(212, 160, 23, 0.85); }
.cell--4 { background: #fef3c7; box-shadow: 0 0 6px rgba(254, 243, 199, 0.6); }
</style>
Quick Info
- Category
- Data Display
- Filename
ActivityHeatmapGrid.astro- Dependencies
- None — pure Astro + CSS
- Tags
- dataheatmapactivitygithubmatrix