diff --git a/src/__tests__/line-series.visual.test.tsx b/src/__tests__/line-series.visual.test.tsx
index 048bb7ac0..bc25de195 100644
--- a/src/__tests__/line-series.visual.test.tsx
+++ b/src/__tests__/line-series.visual.test.tsx
@@ -50,4 +50,26 @@ test.describe('Line series', () => {
const component = await mount();
await expect(component.locator('svg')).toHaveScreenshot();
});
+
+ // TODO: take a screenshot and unskip the test
+ test.skip('Vertical line tooltip', async ({mount}) => {
+ const data = {
+ series: {
+ data: [
+ {
+ type: 'line',
+ name: 'Line series',
+ data: [
+ {x: 10, y: 10},
+ {x: 10, y: 50},
+ ],
+ },
+ ],
+ },
+ } as ChartData;
+
+ const component = await mount();
+ component.hover();
+ await expect(component.locator('svg')).toHaveScreenshot();
+ });
});
diff --git a/src/utils/chart/get-closest-data.ts b/src/utils/chart/get-closest-data.ts
index 4df09504b..8cd6709a5 100644
--- a/src/utils/chart/get-closest-data.ts
+++ b/src/utils/chart/get-closest-data.ts
@@ -41,29 +41,17 @@ export type ShapePoint = {
series: ChartSeries;
};
-function getClosestPointsByXValue(x: number, y: number, points: ShapePoint[]) {
- const sorted = sort(points, (p) => p.x);
- const closestXIndex = bisector((p) => p.x).center(sorted, x);
- if (closestXIndex === -1) {
- return [];
- }
-
- const closestX = sorted[closestXIndex].x;
- const closestPoints = sort(
- points.filter((p) => p.x === closestX),
- (p) => p.y0,
- );
-
+function getClosestYIndex(items: ShapePoint[], y: number) {
let closestYIndex = -1;
- if (y < closestPoints[0]?.y0) {
+ if (y < items[0]?.y0) {
closestYIndex = 0;
- } else if (y > closestPoints[closestPoints.length - 1]?.y1) {
- closestYIndex = closestPoints.length - 1;
+ } else if (y > items[items.length - 1]?.y1) {
+ closestYIndex = items.length - 1;
} else {
- closestYIndex = closestPoints.findIndex((p) => y > p.y0 && y < p.y1);
+ closestYIndex = items.findIndex((p) => y > p.y0 && y < p.y1);
if (closestYIndex === -1) {
const sortedY = sort(
- closestPoints.map((p, index) => ({index, y: p.y1 + (p.y0 - p.y1) / 2})),
+ items.map((p, index) => ({index, y: p.y1 + (p.y0 - p.y1) / 2})),
(p) => p.y,
);
const sortedYIndex = bisector<{y: number}, number>((p) => p.y).center(sortedY, y);
@@ -71,6 +59,29 @@ function getClosestPointsByXValue(x: number, y: number, points: ShapePoint[]) {
}
}
+ return closestYIndex;
+}
+
+function getClosestPointsByXValue(x: number, y: number, points: ShapePoint[]) {
+ const sorted = sort(points, (p) => p.x);
+ const closestXIndex = bisector((p) => p.x).center(sorted, x);
+ if (closestXIndex === -1) {
+ return [];
+ }
+
+ const closestX = sorted[closestXIndex].x;
+ const filtered = points.filter((p) => p.x === closestX);
+
+ const groupedBySeries = Object.values(groupBy(filtered, (p) => get(p.series, 'id'))).map(
+ (items) => {
+ const sortedByY = sort(items, (p) => p.y0);
+ const index = getClosestYIndex(sortedByY, y);
+ return sortedByY[index === -1 ? 0 : index];
+ },
+ );
+
+ const closestPoints = sort(groupedBySeries, (p) => p.y0);
+ const closestYIndex = getClosestYIndex(closestPoints, y);
return closestPoints.map((p, i) => ({
data: p.data,
series: p.series,