feat: highlight the series nearest the cursor in time chart tooltips#2456
feat: highlight the series nearest the cursor in time chart tooltips#2456alex-fedotyev wants to merge 4 commits into
Conversation
In a multi-series Line/Area chart, the shared tooltip lists every series, so it is hard to tell which row maps to which line when a Group By produces many series. Bold the row for the series whose line is nearest the cursor, updating as the pointer moves vertically and clearing emphasis when the pointer is far from every line. Each Area active dot records its active-point pixel Y into a per-chart ref keyed by dataKey. The tooltip compares the cursor pixel Y (coordinate.y) against those captured positions to pick the nearest series. The comparison is pure pixel space (no axis-scale math), and nothing is highlighted beyond a small distance threshold. Stacked bar and single-series charts are unaffected. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Touched these comments in the same files; replace the em-dashes with plain punctuation to match the rest of the codebase. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
A single-series tooltip has nothing to map back to a line, so skip the nearest-series highlight when the tooltip has one row. Keeps the single-series and stacked-bar cases visually unchanged. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 3f84570 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Greptile SummaryAdds visual emphasis to the tooltip row and line corresponding to the series whose active-dot pixel Y is nearest the cursor in
Confidence Score: 5/5Safe to merge; the change is additive and confined to visual emphasis — it does not affect data fetching, charting data, or any path that existed before. The nearest-series logic is pure and fully unit-tested. Guard conditions correctly prevent emphasis on single-series or empty-space scenarios. The stale-ref edge case was already flagged in a prior review and is a minor UX inconsistency rather than a data or correctness issue; the tooltip derives its nearest key independently from the current payload. No files require special attention for merge safety. Important Files Changed
Sequence DiagramsequenceDiagram
participant RC as Recharts Engine
participant CAD as CaptureActiveDot
participant Ref as activePointYByKeyRef
participant TT as HDXLineChartTooltip
participant FN as findNearestSeriesKey
RC->>CAD: render(cx, cy, dataKey) for each visible series
CAD->>Ref: captureRef.current.set(dataKey, cy)
RC->>TT: render(payload, coordinate.y)
TT->>Ref: read activePointYByKeyRef.current
TT->>FN: findNearestSeriesKey(ref, typedPayload keys, coordinate.y, 30px)
FN-->>TT: nearestSeriesKey (or undefined)
TT-->>RC: ChartTooltipItem(highlighted / dimmed per row)
Note over RC,Ref: onMouseMove (prior frame)
RC->>Ref: read activePointYByKey
RC->>FN: findNearestSeriesKey(ref, all ref keys, chartY, 30px)
FN-->>RC: nextNearest
RC->>RC: setNearestSeriesKey (only if changed)
RC-->>RC: Area strokeWidth/strokeOpacity emphasis
Reviews (2): Last reviewed commit: "feat: emphasize the nearest series' line..." | Re-trigger Greptile |
E2E Test Results✅ All tests passed • 197 passed • 3 skipped • 1381s
Tests ran across 4 shards in parallel. |
Bolding the tooltip row alone still leaves the eye hunting for which line it maps to. Lift the nearest-series key into chart state, computed on mouse-move from the pixel Y the active dots already capture, and use it to thicken the nearest line to 2.5px while fading the others to 50% stroke opacity. The tooltip mirrors this: the nearest row stays bold and the rest dim to 50%. Only applies with more than one line shown, and is cleared on the click-frozen tooltip path, matching the existing scope. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
🔵 Tier 2 — Low RiskSmall, isolated change with no API route or data model modifications. Why this tier:
Review process: AI review + quick human skim (target: 5–15 min). Reviewer validates AI assessment and checks for domain-specific concerns. Stats
|
Multi-series Line and Area chart tooltips list every series at the hovered time. When a Group By produces many series, it is hard to tell which tooltip row maps to which line. This bolds the row for the series whose line is nearest the cursor and updates it as the pointer moves up and down, so a row is easy to trace back to its line.
HDX-4531
Summary
In the shared tooltip for
HDXMultiSeriesTimeChart, the row for the series nearest the cursor renders atfont-weight: 600(the same weight the legend uses for a selected series). The highlighted row updates as the pointer moves vertically and clears when the pointer is farther than a small threshold from every line, so nothing is emphasized in empty space.The nearest series is found in pure pixel space. Each Area's active dot records its active-point pixel Y, and the tooltip compares those positions against the cursor's pixel Y (
coordinate.y). No axis-scale reconstruction is involved, which matters because the y domain is often[0, 'auto'].Changes
ChartUtils.tsx: new pure helperfindNearestSeriesKey(seriesYByKey, candidateKeys, pointerY, maxDistancePx)that returns the nearest series' key within the threshold, orundefined. Isolated so the geometry is unit-testable without rendering Recharts.HDXMultiSeriesTimeChart.tsx: a small capturing active dot on the<Area>branch records each series' active-point pixel Y into a per-chart ref, keyed bydataKey. It still draws the same dot Recharts renders by default. The tooltip reads the ref to bold the nearest row. Highlighting only applies when more than one series is shown.ChartTooltip.tsx:ChartTooltipItemtakes an optionalhighlightedprop that sets the row weight to 600. Backward compatible; existing callers are unaffected.Why a ref read during render
Recharts renders the graphical items and their active dots before it renders the tooltip in the same commit, so the captured dot positions are current when the tooltip reads them. Both the capture write and the tooltip read touch a ref during render; this mirrors the existing pattern in
TimelineMouseCursorandTimelineXAxis, and thereact-hooks/refsdisable is annotated with the reason.Out of scope
Stacked bar uses
activeBarrather thanactiveDot, and vertical stacking makes "nearest line" meaningless, so it is intentionally untouched. Single-series charts have nothing to disambiguate, so highlighting is skipped there. Both cases were verified to render with no bold row.Test plan
yarn lint:fix,make ci-lintmake ci-unit, with new unit tests forfindNearestSeriesKey: nearest within threshold, none within threshold, undefined pointer, undefined map, empty candidate list, candidate absent from the map skipped, tie resolves to the first candidate, inclusive boundary atmaxDistancePxServiceNamewith several series:Before this change every tooltip row rendered at the same weight. Before/after captures in light and dark are ready to attach.
[ui-states: allow]
[viewport: allow]
[no-story: allow]