From 068125d52c396a8b0a89c3a94ea9dbd385d788ba Mon Sep 17 00:00:00 2001 From: Raj Jaiswal Date: Wed, 22 Apr 2026 17:22:33 +0100 Subject: [PATCH 1/2] fix: disable cursor line and hover markers for heatmap series Heatmap cells don't benefit from the vertical cursor line or point markers shown on hover. Exclude heatmap from both, matching the existing behavior for column/errorbar series. Renamed hasColumnSeries to hideCursorLine for clarity. --- src/core/chart-api/chart-extra-tooltip.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/core/chart-api/chart-extra-tooltip.tsx b/src/core/chart-api/chart-extra-tooltip.tsx index dedaed34..d9c8cce2 100644 --- a/src/core/chart-api/chart-extra-tooltip.tsx +++ b/src/core/chart-api/chart-extra-tooltip.tsx @@ -149,8 +149,10 @@ export class ChartExtraTooltip extends AsyncStore { const pointRect = point ? getPointRect(point) : getGroupRect(group.slice(0, 1)); const groupRect = getGroupRect(group); // The cursor is not shown when column series are present (a UX decision). - const hasColumnSeries = getChartSeries(this.context.chart()).some((s) => s.type === "column"); - this.cursor.create(groupRect, point, group, !hasColumnSeries); + const hideCursorLine = getChartSeries(this.context.chart()).some( + (s) => s.type === "column" || s.type === "heatmap", + ); + this.cursor.create(groupRect, point, group, !hideCursorLine); this.targetTrack.rect(this.context.chart().renderer, { ...pointRect, ...this.commonTrackAttrs }); this.groupTrack.rect(this.context.chart().renderer, { ...groupRect, ...this.commonTrackAttrs }); }; @@ -238,7 +240,8 @@ class HighlightCursorCartesian { isPointVisible(point) && !isXThreshold(point.series) && point.series.type !== "column" && - point.series.type !== "errorbar" + point.series.type !== "errorbar" && + point.series.type !== "heatmap" ); }; } From c5e7dc827ce3b881b7c8128d87a78d3540b28411 Mon Sep 17 00:00:00 2001 From: Raj Jaiswal Date: Mon, 27 Apr 2026 17:07:25 +0100 Subject: [PATCH 2/2] feat: add heatmap demo page --- pages/03-core/heatmap.page.tsx | 125 +++++++++++++++++++++++++++++++++ pages/common/use-highcharts.ts | 8 ++- 2 files changed, 131 insertions(+), 2 deletions(-) create mode 100644 pages/03-core/heatmap.page.tsx diff --git a/pages/03-core/heatmap.page.tsx b/pages/03-core/heatmap.page.tsx new file mode 100644 index 00000000..22af22f3 --- /dev/null +++ b/pages/03-core/heatmap.page.tsx @@ -0,0 +1,125 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import CoreChart from "../../lib/components/internal-do-not-use/core-chart"; +import { Page } from "../common/templates"; +import { useHighcharts } from "../common/use-highcharts"; +import pseudoRandom from "../utils/pseudo-random"; + +const INSTANCE_COUNT = 10; +const PERIOD = 60000; // 1 minute in ms +const POINTS_PER_INSTANCE = 100; +const START_TIME = Date.now() - POINTS_PER_INSTANCE * PERIOD; + +function generateHeatmapData() { + const instances = Array.from({ length: INSTANCE_COUNT }, (_, i) => `i-${String(i).padStart(16, "0")}`); + + const series = instances.map((name, yIndex) => { + const baseValue = 0.5 + pseudoRandom() * 2.5; + const data: [number, number, number][] = []; + for (let x = 0; x < POINTS_PER_INSTANCE; x++) { + const timestamp = START_TIME + x * PERIOD; + const value = baseValue + (pseudoRandom() - 0.5) * 0.5; + data.push([timestamp, yIndex, value]); + } + return { + name, + type: "heatmap" as const, + data, + borderWidth: 0, + borderRadius: 0, + pointPadding: 0, + showInLegend: false, + colsize: PERIOD, + }; + }); + + return { series, instances }; +} + +const { series, instances } = generateHeatmapData(); + +export default function () { + const highcharts = useHighcharts({ heatmap: true }); + + return ( + + + + ); +} diff --git a/pages/common/use-highcharts.ts b/pages/common/use-highcharts.ts index d665197c..2f0bb0dd 100644 --- a/pages/common/use-highcharts.ts +++ b/pages/common/use-highcharts.ts @@ -11,7 +11,8 @@ export function useHighcharts({ xrange = false, solidgauge = false, boost = false, -}: { more?: boolean; xrange?: boolean; solidgauge?: boolean; boost?: boolean } = {}) { + heatmap = false, +}: { more?: boolean; xrange?: boolean; solidgauge?: boolean; boost?: boolean; heatmap?: boolean } = {}) { const [highcharts, setHighcharts] = useState(null); useEffect(() => { @@ -33,6 +34,9 @@ export function useHighcharts({ if (boost) { await import("highcharts/modules/boost"); } + if (heatmap) { + await import("highcharts/modules/heatmap"); + } if (isDevelopment) { await import("highcharts/modules/debugger"); @@ -42,7 +46,7 @@ export function useHighcharts({ }; load(); - }, [more, xrange, solidgauge, boost]); + }, [more, xrange, solidgauge, boost, heatmap]); return highcharts; }