Skip to content

Commit 8aa7ea8

Browse files
Abdkhan14Abdullah Khan
andauthored
feat(explore-suspect-attrs): Positioning floating trigger to the bottom right (#94939)
Always positioning at the bottom right prevents the trigger from covering the selected region. https://github.com/user-attachments/assets/af27c944-b830-4eb2-b283-8e7b8ccf7dc1 --------- Co-authored-by: Abdullah Khan <abdullahkhan@PG9Y57YDXQ.local>
1 parent f57c7e8 commit 8aa7ea8

File tree

3 files changed

+48
-35
lines changed

3 files changed

+48
-35
lines changed

static/app/views/explore/components/suspectTags/floatingTrigger.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type Props = {
2121

2222
export function FloatingTrigger({boxSelectOptions, triggerWrapperRef, chartInfo}: Props) {
2323
const router = useRouter();
24-
const pageCoords = boxSelectOptions.pageCoords;
24+
const triggerPosition = boxSelectOptions.floatingTriggerPosition;
2525

2626
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
2727
const {openDrawer} = useDrawer();
@@ -73,15 +73,15 @@ export function FloatingTrigger({boxSelectOptions, triggerWrapperRef, chartInfo}
7373
}
7474
}, [boxSelectOptions, chartInfo, isDrawerOpen, openDrawer]);
7575

76-
if (!pageCoords) return null;
76+
if (!triggerPosition) return null;
7777

7878
return createPortal(
7979
<div
8080
ref={triggerWrapperRef}
8181
style={{
8282
position: 'absolute',
83-
top: pageCoords.y,
84-
left: pageCoords.x,
83+
top: triggerPosition.top,
84+
left: triggerPosition.left,
8585
}}
8686
>
8787
<List>

static/app/views/explore/hooks/useChartBoxSelect.spec.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ describe('useChartBoxSelect', () => {
2626
const mockChartInstance = {
2727
getModel: jest.fn(),
2828
dispatchAction: jest.fn(),
29+
convertToPixel: jest.fn().mockReturnValue([100, 200]),
30+
getDom: jest.fn().mockReturnValue({
31+
getBoundingClientRect: jest.fn().mockReturnValue({
32+
left: 50,
33+
top: 100,
34+
}),
35+
}),
2936
};
3037

3138
const mockAxis = {

static/app/views/explore/hooks/useChartBoxSelect.tsx

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,9 @@ export type BoxSelectOptions = {
2525
} | null;
2626
brush: EChartsOption['brush'];
2727
clearSelection: () => void;
28+
floatingTriggerPosition: {left: number; top: number} | null;
2829
onBrushEnd: EChartBrushEndHandler;
2930
onBrushStart: EChartBrushStartHandler;
30-
pageCoords: {x: number; y: number} | null;
3131
reActivateSelection: () => void;
3232
toolBox: ToolboxComponentOption | undefined;
3333
};
@@ -64,7 +64,10 @@ export function useChartBoxSelect({
6464

6565
// This exposes the page coordinates when the user finishes drawing the box. This is used
6666
// to render floating CTAs on top of the chart.
67-
const [pageCoords, setPageCoords] = useState<{x: number; y: number} | null>(null);
67+
const [floatingTriggerPosition, setFloatingTriggerPosition] = useState<{
68+
left: number;
69+
top: number;
70+
} | null>(null);
6871

6972
// This increments a counter to force a re-activation of the brush mode. We expose the
7073
// re-activation function in the return value, so that the parent component can call it
@@ -96,47 +99,50 @@ export function useChartBoxSelect({
9699

97100
const area = evt.areas[0];
98101

102+
const [x0, x1] = area.coordRange[0];
103+
const [y0, y1] = area.coordRange[1];
104+
105+
const clampedCoordRange: [[number, number], [number, number]] = [
106+
[Math.max(xMin, x0), Math.min(xMax, x1)],
107+
[Math.max(yMin, y0), Math.min(yMax, y1)],
108+
];
109+
99110
const newBrushArea: EchartBrushAreas = [
100111
{
101112
...area,
102-
coordRange: [
103-
[
104-
Math.max(xMin, area.coordRange[0][0]),
105-
Math.min(xMax, area.coordRange[0][1]),
106-
],
107-
[
108-
Math.max(yMin, area.coordRange[1][0]),
109-
Math.min(yMax, area.coordRange[1][1]),
110-
],
111-
],
113+
coordRange: clampedCoordRange,
112114
},
113115
];
114116

115117
setBrushArea(newBrushArea);
116-
},
117-
[chartRef]
118-
);
119118

120-
useEffect(() => {
121-
const handleMouseUp = (e: MouseEvent) => {
122-
if (brushArea) {
123-
setPageCoords({x: e.clientX, y: e.clientY + window.scrollY});
124-
} else {
125-
setPageCoords(null);
126-
}
127-
};
119+
// Get the bottom right coordinates of the box
120+
const [clamped_x1, clamped_y0] = [clampedCoordRange[0][1], clampedCoordRange[1][0]];
128121

129-
const wrapper = chartWrapperRef.current;
130-
if (!wrapper) return;
122+
// Convert the bottom right coordinates to pixel coordinates, so that we can use them to
123+
// absolutely position the floating CTAs.
124+
const [clamped_x1_pixels, clamped_y0_pixels] = chart.convertToPixel(
125+
{xAxisIndex: 0, yAxisIndex: 0},
126+
[clamped_x1, clamped_y0]
127+
);
131128

132-
wrapper.addEventListener('mouseup', handleMouseUp);
133-
}, [brushArea, chartWrapperRef]);
129+
const chartRect = chart.getDom().getBoundingClientRect();
130+
131+
if (chartRect) {
132+
setFloatingTriggerPosition({
133+
left: chartRect.left + clamped_x1_pixels,
134+
top: chartRect.top + clamped_y0_pixels + window.scrollY,
135+
});
136+
}
137+
},
138+
[chartRef]
139+
);
134140

135141
const clearSelection = useCallback(() => {
136142
const chartInstance = chartRef.current?.getEchartsInstance();
137143
chartInstance?.dispatchAction({type: 'brush', areas: []});
138144
setBrushArea(null);
139-
setPageCoords(null);
145+
setFloatingTriggerPosition(null);
140146
}, [chartRef]);
141147

142148
const handleOutsideClick = useCallback(
@@ -199,7 +205,7 @@ export function useChartBoxSelect({
199205
chartRef.current,
200206
enableBrushMode,
201207
handleOutsideClick,
202-
pageCoords,
208+
floatingTriggerPosition,
203209
forceReActivateSelection,
204210
]);
205211

@@ -237,7 +243,7 @@ export function useChartBoxSelect({
237243
onBrushEnd,
238244
onBrushStart,
239245
toolBox,
240-
pageCoords,
246+
floatingTriggerPosition,
241247
reActivateSelection,
242248
clearSelection,
243249
};
@@ -247,7 +253,7 @@ export function useChartBoxSelect({
247253
brush,
248254
toolBox,
249255
onBrushStart,
250-
pageCoords,
256+
floatingTriggerPosition,
251257
reActivateSelection,
252258
clearSelection,
253259
]);

0 commit comments

Comments
 (0)