diff --git a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx index b3e47a0dcff9..c4929c9d9459 100644 --- a/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx +++ b/packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx @@ -134,7 +134,7 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { const theme = useTheme(); const classes = useUtilityClasses({ ...defaultizedProps, theme }); - const { left, top, width, height } = useDrawingArea(); + const { left, top, width, height, isPointInside } = useDrawingArea(); const tickSize = disableTicks ? 4 : tickSizeProp; @@ -217,9 +217,8 @@ function ChartsXAxis(inProps: ChartsXAxisProps) { const xTickLabel = labelOffset ?? 0; const yTickLabel = positionSign * (tickSize + 3); - const showTick = offset >= left - 1 && offset <= left + width + 1; - const showTickLabel = - offset + xTickLabel >= left - 1 && offset + xTickLabel <= left + width + 1; + const showTick = isPointInside({ x: offset, y: -1 }, { direction: 'x' }); + const showTickLabel = isPointInside({ x: offset + xTickLabel, y: -1 }, { direction: 'x' }); return ( {!disableTicks && showTick && ( diff --git a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx index 55c2ac3e08af..281ce8d1b3d2 100644 --- a/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx +++ b/packages/x-charts/src/ChartsYAxis/ChartsYAxis.tsx @@ -81,7 +81,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { const classes = useUtilityClasses({ ...defaultizedProps, theme }); - const { left, top, width, height } = useDrawingArea(); + const { left, top, width, height, isPointInside } = useDrawingArea(); const tickSize = disableTicks ? 4 : tickSizeProp; @@ -171,7 +171,7 @@ function ChartsYAxis(inProps: ChartsYAxisProps) { const skipLabel = typeof tickLabelInterval === 'function' && !tickLabelInterval?.(value, index); - const showLabel = offset >= top - 1 && offset <= height + top + 1; + const showLabel = isPointInside({ x: -1, y: offset }, { direction: 'y' }); if (!showLabel) { return null; diff --git a/packages/x-charts/src/context/DrawingProvider.tsx b/packages/x-charts/src/context/DrawingProvider.tsx index 26dee3c5a414..cf851ba3b350 100644 --- a/packages/x-charts/src/context/DrawingProvider.tsx +++ b/packages/x-charts/src/context/DrawingProvider.tsx @@ -42,10 +42,18 @@ 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. + * @param {Object} options The options of the check. + * @param {Element} [options.targetElement] The element to check if it is allowed to overflow the drawing area. + * @param {'x' | 'y'} [options.direction] The direction to check. * @returns {boolean} `true` if the point is inside the drawing area, `false` otherwise. */ - isPointInside: (point: { x: number; y: number }, targetElement?: Element) => boolean; + isPointInside: ( + point: { x: number; y: number }, + options?: { + targetElement?: Element; + direction?: 'x' | 'y'; + }, + ) => boolean; }; export const DrawingContext = React.createContext< @@ -87,17 +95,24 @@ export function DrawingProvider(props: DrawingProviderProps) { const chartId = useId(); const isPointInside = React.useCallback( - ({ x, y }, targetElement) => { + ({ x, y }, options) => { // For element allowed to overflow, wrapping them in make them fully part of the drawing area. - if (targetElement && targetElement.closest('[data-drawing-container]')) { + if (options?.targetElement && options?.targetElement.closest('[data-drawing-container]')) { return true; } - return ( - x >= drawingArea.left && - x <= drawingArea.left + drawingArea.width && - y >= drawingArea.top && - y <= drawingArea.top + drawingArea.height - ); + + const isInsideX = x >= drawingArea.left - 1 && x <= drawingArea.left + drawingArea.width; + const isInsideY = y >= drawingArea.top - 1 && y <= drawingArea.top + drawingArea.height; + + if (options?.direction === 'x') { + return isInsideX; + } + + if (options?.direction === 'y') { + return isInsideY; + } + + return isInsideX && isInsideY; }, [drawingArea], ); diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index f20d26f76dcc..83994d170929 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -109,7 +109,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { mousePosition.current.x = svgPoint.x; mousePosition.current.y = svgPoint.y; - if (!drawingArea.isPointInside(svgPoint, event.target as SVGElement)) { + if (!drawingArea.isPointInside(svgPoint, { targetElement: event.target as SVGElement })) { if (mousePosition.current.isInChart) { dispatch({ type: 'exitChart' }); mousePosition.current.isInChart = false;