diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index 543b6951aaa75..a96716f8b22a9 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -65,7 +65,10 @@ const LineChartPro = React.forwardRef(function LineChartPro(props: LineChartProP - + + {/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */} + + {!props.loading && } diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index 11d0f2d3ddc74..59fbed96eb847 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -48,7 +48,10 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( {!props.disableVoronoi && } {props.grid && } - + + {/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */} + + diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index 1b357d023539b..ec1645b701b98 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -165,7 +165,10 @@ const LineChart = React.forwardRef(function LineChart(props: LineChartProps, ref - + + {/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */} + + {!props.loading && } diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index 84ca039c4f4c5..5db75e52ab59f 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -138,7 +138,10 @@ const ScatterChart = React.forwardRef(function ScatterChart(props: ScatterChartP {!props.disableVoronoi && } {props.grid && } - + + {/* The `data-drawing-container` indicates that children are part of the drawing area. Ref: https://github.com/mui/mui-x/issues/13659 */} + + diff --git a/packages/x-charts/src/context/DrawingProvider.tsx b/packages/x-charts/src/context/DrawingProvider.tsx index 2a3b84d186825..26dee3c5a4147 100644 --- a/packages/x-charts/src/context/DrawingProvider.tsx +++ b/packages/x-charts/src/context/DrawingProvider.tsx @@ -42,9 +42,10 @@ export type DrawingArea = { * @param {Object} point The point to check. * @param {number} point.x The x coordinate of the point. * @param {number} point.y The y coordinate of the point. + * @param {Element} targetElement The target element if relevant. * @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise. */ - isPointInside: (point: { x: number; y: number }) => boolean; + isPointInside: (point: { x: number; y: number }, targetElement?: Element) => boolean; }; export const DrawingContext = React.createContext< @@ -86,11 +87,18 @@ export function DrawingProvider(props: DrawingProviderProps) { const chartId = useId(); const isPointInside = React.useCallback( - ({ x, y }) => - x >= drawingArea.left && - x <= drawingArea.left + drawingArea.width && - y >= drawingArea.top && - y <= drawingArea.top + drawingArea.height, + ({ x, y }, targetElement) => { + // For element allowed to overflow, wrapping them in make them fully part of the drawing area. + if (targetElement && targetElement.closest('[data-drawing-container]')) { + return true; + } + return ( + x >= drawingArea.left && + x <= drawingArea.left + drawingArea.width && + y >= drawingArea.top && + y <= drawingArea.top + drawingArea.height + ); + }, [drawingArea], ); diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index 963e53ea143ab..f20d26f76dcc3 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -21,6 +21,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { // Use a ref to avoid rerendering on every mousemove event. const mousePosition = React.useRef({ + isInChart: false, x: -1, y: -1, }); @@ -94,6 +95,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { const handleOut = () => { mousePosition.current = { + isInChart: false, x: -1, y: -1, }; @@ -104,15 +106,17 @@ export const useAxisEvents = (disableAxisListener: boolean) => { const target = 'targetTouches' in event ? event.targetTouches[0] : event; const svgPoint = getSVGPoint(element, target); - mousePosition.current = { - x: svgPoint.x, - y: svgPoint.y, - }; + mousePosition.current.x = svgPoint.x; + mousePosition.current.y = svgPoint.y; - if (!drawingArea.isPointInside(svgPoint)) { - dispatch({ type: 'exitChart' }); + if (!drawingArea.isPointInside(svgPoint, event.target as SVGElement)) { + if (mousePosition.current.isInChart) { + dispatch({ type: 'exitChart' }); + mousePosition.current.isInChart = false; + } return; } + mousePosition.current.isInChart = true; const newStateX = getNewAxisState(xAxis[usedXAxis], svgPoint.x); const newStateY = getNewAxisState(yAxis[usedYAxis], svgPoint.y);