Skip to content

Commit 61151a7

Browse files
authored
Merge pull request #1998 from visualize-admin/fix/tooltip-issues
fix: Chart tooltip issues
2 parents 5a504c8 + d723879 commit 61151a7

File tree

6 files changed

+39
-59
lines changed

6 files changed

+39
-59
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ You can also check the
1616
- Preview via API using iframe (`/preview`) now ignores invalid messages sent
1717
from the parent window
1818
- Selected values are now correctly displayed in the filter panel
19+
- Chart tooltip now wraps in case of long text, instead of going off the
20+
screen
21+
- Pie chart tooltip is now positioned closer to the chart to prevent it from
22+
going off the screen in case of iframe embed
1923

2024
# [5.2.0] - 2025-01-22
2125

app/charts/pie/pie-state.tsx

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { ascending, sum } from "d3-array";
22
import { ScaleOrdinal, scaleOrdinal } from "d3-scale";
33
import { schemeCategory10 } from "d3-scale-chromatic";
4-
import { Pie, PieArcDatum, arc, pie } from "d3-shape";
4+
import { Pie, pie, PieArcDatum } from "d3-shape";
55
import orderBy from "lodash/orderBy";
66
import { useMemo } from "react";
77

@@ -31,7 +31,6 @@ import {
3131
getSortingOrders,
3232
makeDimensionValueSorters,
3333
} from "@/utils/sorting-values";
34-
import { useIsMobile } from "@/utils/use-is-mobile";
3534

3635
import { ChartProps } from "../shared/ChartProps";
3736

@@ -112,7 +111,7 @@ const usePieState = (
112111
label: segment,
113112
color:
114113
fields.color.type === "segment"
115-
? fields.color.colorMapping![dvIri] ?? schemeCategory10[0]
114+
? (fields.color.colorMapping![dvIri] ?? schemeCategory10[0])
116115
: schemeCategory10[0],
117116
};
118117
});
@@ -169,17 +168,7 @@ const usePieState = (
169168
left,
170169
};
171170
const bounds = useChartBounds(width, margins, height);
172-
const { chartWidth, chartHeight } = bounds;
173-
174-
// Pie values
175-
const maxSide = Math.min(chartWidth, chartHeight) / 2;
176-
177-
const innerRadius = 0;
178-
const outerRadius = Math.min(maxSide, 100);
179-
180-
const arcGenerator = arc<Observation, PieArcDatum<Observation>>()
181-
.innerRadius(innerRadius)
182-
.outerRadius(outerRadius);
171+
const { chartWidth } = bounds;
183172

184173
// Pie data
185174
// Sort the pie according to the segments
@@ -216,34 +205,17 @@ const usePieState = (
216205
return `${rounded}% (${fValue})`;
217206
};
218207

219-
const isMobile = useIsMobile();
220-
221208
// Tooltip
222209
const getAnnotationInfo = (
223210
arcDatum: PieArcDatum<Observation>
224211
): TooltipInfo => {
225-
const [x, y] = arcGenerator.centroid(arcDatum);
226212
const datum = arcDatum.data;
227213

228-
const xTranslate = chartWidth / 2;
229-
const yTranslate = chartHeight / 2;
230-
231-
const xAnchor = isMobile ? chartWidth / 2 : x + xTranslate;
232-
const yAnchor = isMobile ? -chartHeight : y + yTranslate;
233-
234-
const xPlacement = isMobile
235-
? "center"
236-
: xAnchor < chartWidth * 0.5
237-
? "right"
238-
: "left";
214+
const xAnchor = chartWidth / 2;
215+
const yAnchor = -4;
239216

240-
const yPlacement = isMobile
241-
? "top"
242-
: yAnchor > chartHeight * 0.2
243-
? "top"
244-
: yAnchor < chartHeight * 0.8
245-
? "bottom"
246-
: "middle";
217+
const xPlacement = "center";
218+
const yPlacement = "top";
247219

248220
return {
249221
xAnchor,
@@ -255,7 +227,7 @@ const usePieState = (
255227
color: colors(getSegment(datum)) as string,
256228
},
257229
values: undefined,
258-
withTriangle: !isMobile,
230+
withTriangle: false,
259231
};
260232
};
261233

app/charts/pie/rendering-utils.ts

Lines changed: 4 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@ import { Transition } from "d3-transition";
55

66
import {
77
maybeTransition,
8-
RenderOptions,
8+
RenderOptions
99
} from "@/charts/shared/rendering-utils";
1010
import { Observation } from "@/domain/data";
1111

12-
import type { BaseType, Selection } from "d3-selection";
12+
import type { Selection } from "d3-selection";
1313

1414
export type RenderDatum = {
1515
key: string;
@@ -43,25 +43,11 @@ export const renderPies = (
4343
.attr("stroke-width", 0)
4444
.on("mouseenter", function (_, d) {
4545
handleMouseEnter(d.arcDatum);
46-
select<SVGPathElement, RenderDatum>(this).call(
47-
(s: Selection<SVGPathElement, RenderDatum, BaseType, unknown>) =>
48-
maybeTransition(s, {
49-
transition,
50-
s: (g) => g.attr("stroke-width", 1),
51-
t: (g) => g.attr("stroke-width", 1),
52-
})
53-
);
46+
select<SVGPathElement, RenderDatum>(this).attr("stroke-width", 1)
5447
})
5548
.on("mouseleave", function () {
5649
handleMouseLeave();
57-
select<SVGPathElement, RenderDatum>(this).call(
58-
(s: Selection<SVGPathElement, RenderDatum, BaseType, unknown>) =>
59-
maybeTransition(s, {
60-
transition,
61-
s: (g) => g.attr("stroke-width", 0),
62-
t: (g) => g.attr("stroke-width", 0),
63-
})
64-
);
50+
select<SVGPathElement, RenderDatum>(this).attr("stroke-width", 0)
6551
})
6652
.call((enter) =>
6753
maybeTransition(enter, {

app/charts/shared/interaction/tooltip-box.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ export const TooltipBox = ({
165165
left: tooltipXBoundary! + margins.left + position.left,
166166
top: mxYOffset(y!, placement) + margins.top + position.top,
167167
transform: mkTranslation(placement),
168+
maxWidth: "100%",
168169
pointerEvents: "none",
169170
}}
170171
>

app/charts/shared/interaction/tooltip-content.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,12 @@ export const TooltipSingle = ({
1616
yError?: string;
1717
}) => {
1818
return (
19-
<Box>
19+
<div>
2020
{xValue && (
2121
<Typography
2222
component="div"
2323
variant="caption"
24-
sx={{ fontWeight: "bold" }}
24+
sx={{ fontWeight: "bold", whiteSpace: "wrap" }}
2525
>
2626
{xValue}
2727
</Typography>
@@ -37,7 +37,7 @@ export const TooltipSingle = ({
3737
{yError ?? null}
3838
</Typography>
3939
)}
40-
</Box>
40+
</div>
4141
);
4242
};
4343

app/charts/shared/interaction/tooltip.tsx

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
1+
import { PieArcDatum } from "d3-shape";
12
import { ReactNode } from "react";
23

4+
import { AreasState } from "@/charts/area/areas-state";
5+
import { GroupedBarsState } from "@/charts/bar/bars-grouped-state";
6+
import { StackedBarsState } from "@/charts/bar/bars-stacked-state";
7+
import { BarsState } from "@/charts/bar/bars-state";
8+
import { ComboLineColumnState } from "@/charts/combo/combo-line-column-state";
9+
import { ComboLineDualState } from "@/charts/combo/combo-line-dual-state";
10+
import { ComboLineSingleState } from "@/charts/combo/combo-line-single-state";
311
import { LinesState } from "@/charts/line/lines-state";
412
import { PieState } from "@/charts/pie/pie-state";
13+
import { ScatterplotState } from "@/charts/scatterplot/scatterplot-state";
514
import { useChartState } from "@/charts/shared/chart-state";
615
import {
716
TooltipBox,
@@ -48,8 +57,16 @@ export type TooltipInfo = {
4857

4958
const TooltipInner = ({ d, type }: { d: Observation; type: TooltipType }) => {
5059
const { bounds, getAnnotationInfo } = useChartState() as
60+
| AreasState
61+
| BarsState
62+
| GroupedBarsState
63+
| StackedBarsState
64+
| ComboLineDualState
65+
| ComboLineSingleState
66+
| ComboLineColumnState
5167
| LinesState
52-
| PieState;
68+
| PieState
69+
| ScatterplotState;
5370
const { margins } = bounds;
5471
const {
5572
xAnchor,
@@ -60,7 +77,7 @@ const TooltipInner = ({ d, type }: { d: Observation; type: TooltipType }) => {
6077
datum,
6178
values,
6279
withTriangle,
63-
} = getAnnotationInfo(d as any);
80+
} = getAnnotationInfo(d as Observation & PieArcDatum<Observation>, []);
6481

6582
if (Number.isNaN(yAnchor)) {
6683
return null;

0 commit comments

Comments
 (0)