@matthitachi/react-heatmap
v1.0.0
Published
A flexible, customizable calendar heatmap component for React, inspired by GitHub's contribution graph
Maintainers
Readme
Heatmap Component
A flexible, customizable calendar heatmap component for React, inspired by GitHub's contribution graph.
Features
- 📅 Flexible Date Ranges - Display any date range with automatic week alignment
- 🎨 Customizable Colors - Define your own color scales and thresholds
- 🌓 Light/Dark Mode - Built-in theme support
- 📱 Responsive - Horizontal scrolling for large date ranges
- 🎯 Interactive - Click and hover handlers for cells
- 🔧 Highly Customizable - Override styles and classes for any element
- 📊 Smart Labels - Automatic month label positioning with overlap prevention
- 🌍 Week Start Options - Start weeks on any day (Sunday, Monday, etc.)
- 💡 TypeScript - Full TypeScript support with exported types
Installation
# If publishing as npm package
npm install @your-org/react-heatmap
# Or copy the component files to your project
cp -r components/common/Heatmap /your-project/components/Basic Usage
import { Heatmap } from '@/components/common/Heatmap';
function MyComponent() {
const data = [
{ date: '2024-01-01', count: 5 },
{ date: '2024-01-02', count: 12 },
{ date: '2024-01-03', count: 0 },
// ... more data
];
return (
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
/>
);
}Props API
Data Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| values | HeatmapValue[] | ✅ | - | Array of { date: string, count: number } objects |
| startDate | string | ✅ | - | Start date in ISO format (YYYY-MM-DD) |
| endDate | string | ✅ | - | End date in ISO format (YYYY-MM-DD) |
Display Options
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| showMonthLabels | boolean | ❌ | true | Show month labels |
| showWeekdayLabels | boolean | ❌ | true | Show weekday labels |
| monthPlacement | 'top' \| 'bottom' | ❌ | 'top' | Position of month labels |
| weekStart | 0-6 | ❌ | 0 | Starting day of week (0=Sunday, 1=Monday, etc.) |
| showLegend | boolean | ❌ | true | Show color legend |
| emptyMessage | string | ❌ | 'No data available...' | Message shown when no data |
Sizing Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| cellSize | number | ❌ | 12 | Size of each cell in pixels |
| cellGap | number | ❌ | 3 | Gap between cells in pixels |
| cellRadius | number | ❌ | 2 | Border radius for cells in pixels |
Color Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| colorScale | ColorScale | ❌ | GitHub greens | Color thresholds object |
| surface | 'light' \| 'dark' | ❌ | 'light' | Theme mode |
Styling Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| className | string | ❌ | - | Custom class for container |
| classNames | HeatmapClassNames | ❌ | - | Override classes for elements |
| style | CSSProperties | ❌ | - | Inline styles for container |
| styles | HeatmapStyles | ❌ | - | Override styles for elements |
Interaction Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| tooltipFormatter | (value) => string | ❌ | Default formatter | Custom tooltip content |
| onClick | (value, event) => void | ❌ | - | Cell click handler |
| onMouseOver | (value, event) => void | ❌ | - | Cell hover handler |
| onMouseLeave | (value, event) => void | ❌ | - | Cell leave handler |
Label Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| monthLabels | string[] | ❌ | ['Jan', 'Feb', ...] | Custom month labels |
| weekdayLabels | string[] | ❌ | ['Sun', 'Mon', ...] | Custom weekday labels |
Advanced Examples
Custom Color Scale
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
colorScale={{
0: '#f0f0f0',
5: '#c6e48b',
10: '#7bc96f',
15: '#239a3b',
20: '#196127',
}}
/>Week Starting on Monday
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
weekStart={1}
weekdayLabels={['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']}
/>Custom Tooltip
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
tooltipFormatter={(value) =>
`${value.count} contributions on ${new Date(value.date).toLocaleDateString()}`
}
/>Dark Mode
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
surface="dark"
/>Month Labels at Bottom
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
monthPlacement="bottom"
/>Minimal Heatmap (No Labels or Legend)
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
showMonthLabels={false}
showWeekdayLabels={false}
showLegend={false}
/>TypeScript Types
interface HeatmapValue {
date: string; // ISO format: YYYY-MM-DD
count: number;
}
interface ColorScale {
[threshold: number]: string;
}
type TooltipFormatter = (value: HeatmapValue) => string;
type CellClickHandler = (value: HeatmapValue, event: MouseEvent<HTMLDivElement>) => void;
type CellHoverHandler = (value: HeatmapValue | null, event: MouseEvent<HTMLDivElement>) => void;Customization Guide
Override Individual Element Classes
The classNames prop allows you to override classes for specific elements:
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
classNames={{
container: 'my-container',
cell: 'my-cell',
cellActive: 'my-active-cell',
cellEmpty: 'my-empty-cell',
tooltip: 'my-tooltip',
legend: 'my-legend',
monthLabel: 'my-month-label',
weekdayLabel: 'my-weekday-label',
}}
/>Override Individual Element Styles
The styles prop allows you to override inline styles:
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
styles={{
container: { backgroundColor: '#f5f5f5', padding: '20px' },
cell: { borderRadius: '4px' },
tooltip: { fontSize: '14px', padding: '8px 12px' },
legend: { justifyContent: 'center' },
}}
/>Default Color Scale
The default color scale uses GitHub-style greens:
{
0: '#ebedf0', // Empty/no activity
2: '#9be9a8', // Low activity
5: '#40c463', // Medium activity
10: '#30a14e', // High activity
20: '#216e39', // Very high activity
}Browser Support
- Chrome (latest)
- Firefox (latest)
- Safari (latest)
- Edge (latest)
Performance Considerations
- The component efficiently handles large date ranges (multiple years)
- Uses
useMemofor expensive calculations - Horizontal scrolling for wide heatmaps
- Optimized re-renders with proper dependency arrays
Accessibility
- Semantic HTML structure
- Keyboard navigation support (when click handlers are provided)
- ARIA labels can be added via
classNamesand custom attributes - High contrast mode compatible
License
MIT
Credits
Inspired by:
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Changelog
v1.0.0
- Initial release
- Full TypeScript support
- Customizable color scales
- Light/Dark mode
- Interactive tooltips
- Click and hover handlers
- Smart month label positioning
- Week start customization
Click Handler
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
onClick={(value, event) => {
console.log(`Clicked on ${value.date} with ${value.count} activities`);
}}
/>Custom Styling
<Heatmap
values={data}
startDate="2024-01-01"
endDate="2024-12-31"
className="my-custom-heatmap"
classNames={{
cell: 'custom-cell',
tooltip: 'custom-tooltip',
}}
styles={{
container: { padding: '24px' },
cell: { borderRadius: '50%' },
}}
/>