Repository navigation
Conversation
|
I ran my review agent on the PR, here are its findings that I deem relevant:
|
There was a problem hiding this comment.
🟡 Changes recommended
Incomplete hover cancellation and timer cleanup allow delayed tooltips and highlights to appear after Escape, legend interactions, or delay changes, while canceled or hidden targets can leave stale cursor previews.
6 open issues
Restore the cursor preview when a pending hover is cancelled · New Clear cursor previews for targets that become invisible · New Legend focus should cancel pending chart-point hover · New Visibility actions should cancel both hover schedulers · New Escape should cancel pending hover even before the tooltip appears · New Cancel the previous hover timer when replacing its debounce · New
What changed in this PR
Adds internal hover debouncing to the core chart to coordinate highlights, legend scrolling, and tooltips in dense charts while keeping cursor previews immediate.
Changes:
- Introduces a shared scheduler implementation for delayed point, group, and legend hover effects.
- Adds cancellation, click-to-pin handling, and visibility checks for pending targets.
- Adds unit tests, browser tests, and a configurable dense-chart demo.
| File | Description |
|---|---|
test/functional/hover-debounce.test.ts |
Adds browser coverage for delayed and immediate hover behavior. |
src/internal/components/chart-legend/index.tsx |
Configures tooltip and scroll timing and distinguishes pointer hover. |
src/core/internal-interfaces.ts |
Defines the internal hoverDebounce prop. |
src/core/components/core-legend.tsx |
Routes legend pointer highlights through the scheduler. |
src/core/chart-core.tsx |
Wires hover delay into chart settings, legends, and tooltips. |
src/core/chart-api/index.tsx |
Coordinates legend scheduling, cursor previews, and cancellation. |
src/core/chart-api/hover-scheduler.ts |
Adds reusable target-aware hover scheduling. |
src/core/chart-api/chart-extra-tooltip.tsx |
Separates cursor previews from tooltip anchor updates. |
src/core/chart-api/chart-extra-pointer.tsx |
Schedules pointer targets and flushes pending hover on click. |
src/core/chart-api/chart-extra-context.tsx |
Adds the hover-delay setting and default. |
src/core/__tests__/common.tsx |
Extends test helpers to accept internal hover props. |
src/core/__tests__/chart-core-hover-debounce.test.tsx |
Covers timing, previews, cancellation, and visibility checks. |
pages/03-core/hover-debounce.page.tsx |
Adds a dense-chart demo with adjustable delay. |
Review effort: Balanced
d12e9a7 to
9c26861
Compare
|
Thanks for the review. All points are addressed in 9c26861:
|
There was a problem hiding this comment.
🟡 Changes recommended
Inconsistent cancellation of delayed hover work causes stale tooltips and highlights after pointer exit or Escape/API actions, and suppresses valid legend highlights during plot-to-legend transitions.
4 open issues
6 resolved since last review
Cancel the previous hover timer when replacing its debounce Escape should cancel pending hover even before the tooltip appears Visibility actions should cancel both hover schedulers Legend focus should cancel pending chart-point hover Clear cursor previews for targets that become invisible Restore the cursor preview when a pending hover is cancelled
Review effort: Balanced
| } | ||
| }; | ||
|
|
||
| private applyHover = (target: PointerHoverTarget) => { |
| if (this.chartExtraPointer.cancelPendingHover()) { | ||
| this.chartExtraTooltip.restoreCursor(); | ||
| } | ||
| this.legendItemHover.cancel(); |
In dense charts, series highlight, legend highlight, legend scroll-into-view and the tooltip all react to every pointer move, which causes a lot of motion. The existing tooltip.debounce only delays the tooltip, so the other effects drift apart from it. Add an internal hoverDebounce prop (number in ms, or true for 300ms) that applies all of these effects together once the pointer settles on a target: - A HoverScheduler owns the delay, the pending target and the timer. The pointer uses it for points and groups; the chart API uses a second instance for legend item hover. - The timer restarts only when the hovered target changes. - The cursor line and point markers are drawn immediately as a preview; series, legend, scroll, tooltip and onHighlight wait. - The legend item tooltip uses the same delay, and tooltip.debounce is ignored while hoverDebounce is set so the delays don't stack. tooltip.debounce is planned for removal once consumers have moved to hoverDebounce. - A click applies the pending hover first, so pinning still works. - Pending hovers are cancelled at the three highlight funnels (highlightActions, clearHighlightActions, highlightChartItems), so keyboard, API, legend and dismiss paths all take precedence. Only Escape with nothing visible, visibility changes and destroy cancel explicitly. A cancelled or rejected preview restores the cursor. - A pending point or group is applied only while the pointer is still on it, and is re-checked for visibility when the delay ends. - Leaving a legend item cancels its pending highlight immediately, Escape also cancels a pending legend tooltip, and losing the plot hover does not cancel a newer legend hover. - The internal legend receives plain tooltip and scroll delays and keeps one tooltip timer, so changing the delay can't leave a stale timer behind. Without hoverDebounce the behavior is unchanged. The prop is internal (like the zoom props) and not part of the public API. Adds a dev page (03-core/hover-debounce) with a dense line chart, unit tests, and browser tests that run against that page.
9c26861 to
665cac7
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved hover scheduling and state issues can show stale tooltips, highlight items after legend teardown, cancel newer cross-legend hovers, and reset cursor previews on redraw.
6 open issues
Preserve preview cursor target across chart redraws · New Scope delayed highlight cleanup to its originating legend · New Cancel pending legend tooltip when highlighting another item · New Cancel pending legend highlight when unmounting the legend · New Escape leaves the pending legend tooltip timer active Pending point hover commits after pointer leaves
2 resolved since last review
Review effort: Balanced
| public showCursor(point: null | Highcharts.Point, group: readonly Highcharts.Point[]) { | ||
| if (!this.tooltipLock && this.chartType === "cartesian") { | ||
| this.createCursor(point, group); | ||
| } |
| }; | ||
| public onLeaveLegendItem = () => this.legendItemHover.cancel(); | ||
| public onClearChartItemsHighlight = () => { | ||
| this.legendItemHover.cancel(); |
| if (!keepLegendHover) { | ||
| this.legendItemHover.cancel(); | ||
| } |
| }, | ||
| }; | ||
| }, []); | ||
| useEffect(() => cancelTooltip, [cancelTooltip]); |

Description
In dense charts, series highlight, legend highlight, legend scroll-into-view and the tooltip all react to every pointer move, which causes a lot of motion. The existing
tooltip.debounceonly delays the tooltip, so the other effects drift apart from it.This adds an internal
hoverDebounceprop to core chart (a number in ms, ortruefor 300ms) that applies all of these effects together once the pointer settles on a target.HoverScheduler(src/core/chart-api/hover-scheduler.ts) owns the delay, the pending target and the timer. The pointer uses it for points and groups, and the chart API uses a second instance for legend item hover.onHighlightwait for the delay.tooltip.debounceis ignored whilehoverDebounceis set, so the delays don't stack.Without
hoverDebounce, behavior is unchanged. Like the zoom props, the prop lives ininternal-interfaces.tsand isn't part of the public API, so the documenter snapshot doesn't change.Related links, issue #, if available: n/a
How has this been tested?
src/core/__tests__/chart-core-hover-debounce.test.tsx. They cover delay and restart, the immediate cursor, legend hover and its tooltip, click to pin, the cancellation cases, the visibility re-check, and the default with no delay. Full unit suite: 467 passing.test/functional/hover-debounce.test.ts, using real WebDriver mouse input against the dev page with a 1000ms delay. They check that the cursor shows at once while the tooltip and highlights wait, that the tooltip stays on the previous point until the pointer rests, the legend-hover delay, and the no-delay baseline. Run withnpm run test:functional. Not run yet; the same scenarios were checked by hand in a browser.pages/03-core/hover-debounce.page.tsx(#/03-core/hover-debounce) has a line chart with 40 series and a height-limited legend. Set the delay in page settings, or with thehoverDebounceURL parameter; 0 shows the current behavior.Review checklist
The following items are to be evaluated by the author(s) and the reviewer(s).
Correctness
CONTRIBUTING.md.CONTRIBUTING.md.Security
checkSafeUrlfunction.Testing
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.
Screen.Recording.2026-11-11.at.15.52.17.mov