fix: responsive heatmap sizing with max cell size and centering

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Christopher Mühl 2026-04-08 13:45:09 +02:00
parent e46773de22
commit 57cc31827b
No known key found for this signature in database
GPG key ID: 925AC7D69955293F
2 changed files with 19 additions and 8 deletions

File diff suppressed because one or more lines are too long

View file

@ -109,13 +109,23 @@ export function renderHeatmap(
.domain([0, maxHours])
.range(colors);
const { cellSize, cellGap, marginTop, marginLeft, marginBottom } = config;
const step = cellSize + cellGap;
const { cellGap, marginTop, marginLeft, marginBottom } = config;
const numWeeks = (max(cells, (c) => c.week) ?? 0) + 1;
// Compute cell size to fill available width, capped at 16px
const containerWidth = container.clientWidth || 800;
const maxCellSize = 18;
const cellSize = Math.min(maxCellSize, Math.max(2, Math.floor((containerWidth - marginLeft) / numWeeks) - cellGap));
const step = cellSize + cellGap;
const svgWidth = marginLeft + numWeeks * step;
const svgHeight = marginTop + 7 * step + marginBottom;
const svg = select(container)
const wrapper = document.createElement('div');
wrapper.style.maxWidth = `${svgWidth}px`;
wrapper.style.margin = '0 auto';
container.appendChild(wrapper);
const svg = select(wrapper)
.append('svg')
.attr('width', svgWidth)
.attr('height', svgHeight)
@ -153,7 +163,8 @@ export function renderHeatmap(
// Tooltip
const tooltip = createTooltip();
container.appendChild(tooltip);
wrapper.style.position = 'relative';
wrapper.appendChild(tooltip);
// Cells
svg
@ -175,9 +186,9 @@ export function renderHeatmap(
tooltip.style.display = 'block';
const rect = (event.target as SVGRectElement).getBoundingClientRect();
const containerRect = container.getBoundingClientRect();
tooltip.style.left = `${rect.left - containerRect.left + cellSize / 2}px`;
tooltip.style.top = `${rect.top - containerRect.top - 40}px`;
const wrapperRect = wrapper.getBoundingClientRect();
tooltip.style.left = `${rect.left - wrapperRect.left + cellSize / 2}px`;
tooltip.style.top = `${rect.top - wrapperRect.top - 40}px`;
})
.on('mouseleave', function () {
tooltip.style.display = 'none';