From 5565182f3b1168252b1b9b80c1bc38b013cecac9 Mon Sep 17 00:00:00 2001 From: Francis Cao Date: Thu, 28 May 2026 10:40:07 -0700 Subject: [PATCH] fix heatmap viewport stretching. Polish UI/tooltips --- .../(reports)/heatmaps/Heatmap.module.css | 7 +++ .../(reports)/heatmaps/Heatmap.tsx | 46 ++++++++++++------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.module.css b/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.module.css index de6c640fa..d02b815b1 100644 --- a/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.module.css +++ b/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.module.css @@ -42,6 +42,12 @@ color: inherit; } +.pageMetric { + flex: 0 0 88px; + text-align: right; + font-variant-numeric: tabular-nums; +} + .pageButton:hover { background: var(--interactive-bg-hover); } @@ -125,6 +131,7 @@ border-radius: 8px; background: var(--surface-sunken); flex: 0 0 auto; + margin-inline: auto; } .canvasClip { diff --git a/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.tsx b/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.tsx index c9f0a87e8..34f03e456 100644 --- a/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.tsx +++ b/src/app/(main)/websites/[websiteId]/(reports)/heatmaps/Heatmap.tsx @@ -146,6 +146,12 @@ function PageList({ mode: HeatmapMode; hasSearch: boolean; }) { + const getPageMetricTitle = (page: HeatmapResult['pages'][number]) => { + const metricLabel = mode === 'scroll' ? 'scroll events' : 'clicks'; + + return `${formatLongNumber(page.sessions)} visitors - ${formatLongNumber(page.count)} ${metricLabel}`; + }; + return ( Pages @@ -161,8 +167,8 @@ function PageList({ > {page.urlPath} - - {formatLongNumber(mode === 'scroll' ? page.sessions : page.count)} + + {formatLongNumber(page.sessions)} @@ -264,11 +270,15 @@ function ClickHeatmapView({ const overlayGutter = Math.max(48, Math.round((viewport?.width ?? 1920) * 0.04)); const maxPointX = visible.reduce((max, point) => Math.max(max, point.pageX), 0); const maxPointY = visible.reduce((max, point) => Math.max(max, point.pageY), 0); - const baseWidth = Math.max(snapshot?.pageW ?? 0, viewport?.pageW ?? 0, maxPointX + overlayGutter, 1200); - const baseHeight = Math.max(snapshot?.pageH ?? 0, viewport?.pageH ?? 0, maxPointY + overlayGutter, 640); + const baseWidth = Math.max(viewport?.pageW ?? 0, maxPointX + overlayGutter, 1); + const baseHeight = Math.max(viewport?.pageH ?? 0, maxPointY + overlayGutter, 640); + const renderWidth = snapshot?.pageW ?? baseWidth; + const renderHeight = snapshot?.pageH ?? baseHeight; + const hasMeasuredWidth = Boolean(snapshot?.pageW || viewport?.pageW || maxPointX); + const canvasWidth = hasMeasuredWidth ? `min(100%, ${renderWidth}px)` : '100%'; const overlayPageW = snapshot?.pageW ?? viewport?.pageW ?? baseWidth; const overlayPageH = snapshot?.pageH ?? viewport?.pageH ?? baseHeight; - const showSnapshot = baseWidth > 0 && showPage && hasSnapshotImage; + const showSnapshot = renderWidth > 0 && showPage && hasSnapshotImage; const showOverlay = !showSnapshot || snapshotReady; const totalClicks = visible.reduce((sum, point) => sum + point.count, 0); const showLoading = isLoading; @@ -308,9 +318,9 @@ function ClickHeatmapView({
{showLoading ? ( @@ -397,9 +407,13 @@ function ScrollHeatmapView({ }, [hasSnapshotImage, showPage, snapshot?.id]); const { buckets = [], totalSessions = 0, pageW = 0, pageH = 0, viewportW = 0, viewportH = 0 } = scroll ?? {}; - const baseWidth = Math.max(snapshot?.pageW ?? 0, pageW, 1200); - const baseHeight = Math.max(snapshot?.pageH ?? 0, pageH, 640); - const showSnapshot = baseWidth > 0 && showPage && hasSnapshotImage; + const baseWidth = Math.max(pageW, 1); + const baseHeight = Math.max(pageH, 640); + const renderWidth = snapshot?.pageW ?? baseWidth; + const renderHeight = snapshot?.pageH ?? baseHeight; + const hasMeasuredWidth = Boolean(snapshot?.pageW || pageW); + const canvasWidth = hasMeasuredWidth ? `min(100%, ${renderWidth}px)` : '100%'; + const showSnapshot = renderWidth > 0 && showPage && hasSnapshotImage; const showOverlay = !showSnapshot || snapshotReady; const hasScrollData = Boolean(scroll && totalSessions > 0 && pageW && pageH && viewportW); const showLoading = isLoading; @@ -456,9 +470,9 @@ function ScrollHeatmapView({
{showLoading ? ( @@ -484,10 +498,10 @@ function ScrollHeatmapView({ height: `${Math.max(0, band.toPct - band.fromPct)}%`, background: intensity > 0 ? `hsla(${hue}, 90%, 55%, ${0.12 + intensity * 0.45})` : 'none', }} - title={`${band.toPct}% depth • ${formatLongNumber(band.reached)} sessions reached`} + title={`${band.toPct}% depth - ${formatLongNumber(band.reached)} sessions reached`} > - {band.toPct}% depth • {Math.round(intensity * 100)}% reached + {band.toPct}% depth - {Math.round(intensity * 100)}% reached
);