diff --git a/docs/data/charts/tooltip/CustomAxisTooltip.js b/docs/data/charts/tooltip/CustomAxisTooltip.js index b65f7d3df4b2..0d0693111c49 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltip.js +++ b/docs/data/charts/tooltip/CustomAxisTooltip.js @@ -1,184 +1,82 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; -import { useAxisTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -function usePointer() { - const svgRef = useSvgRef(); - const popperRef = React.useRef(null); - const positionRef = React.useRef({ x: 0, y: 0 }); - - // Use a ref to avoid rerendering on every mousemove event. - const [pointer, setPointer] = React.useState({ - isActive: false, - isMousePointer: false, - pointerHeight: 0, - }); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return () => {}; - } - - const handleOut = (event) => { - if (event.pointerType !== 'mouse') { - setPointer((prev) => ({ - ...prev, - isActive: false, - })); - } - }; - - const handleEnter = (event) => { - setPointer({ - isActive: true, - isMousePointer: event.pointerType === 'mouse', - pointerHeight: event.height, - }); - }; - - const handleMove = (event) => { - positionRef.current = { - x: event.clientX, - y: event.clientY, - }; - popperRef.current?.update(); - }; - - element.addEventListener('pointerenter', handleEnter); - element.addEventListener('pointerup', handleOut); - element.addEventListener('pointermove', handleMove); - - return () => { - element.removeEventListener('pointerenter', handleEnter); - element.removeEventListener('pointerup', handleOut); - element.removeEventListener('pointermove', handleMove); - }; - }, [svgRef]); - - return { - ...pointer, - popperRef, - anchorEl: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} +import { ChartsTooltipContainer, useAxisTooltip } from '@mui/x-charts/ChartsTooltip'; export function CustomAxisTooltip() { const tooltipData = useAxisTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { + if (!tooltipData) { // No data to display return null; } - - // The pointer type can be used to have different behavior based on pointer type. - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - + theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], + m: 1, + border: 'solid', + borderWidth: 2, + borderColor: 'divider', + table: { borderSpacing: 0 }, + thead: { + td: { + px: 1.5, + py: 0.75, + borderBottom: 'solid', + borderWidth: 2, + borderColor: 'divider', }, }, - ]} - > - - - - -
- {tooltipData.axisFormattedValue} + }, + }} + > + + + + + + + + {tooltipData.seriesItems.map((seriesItem) => ( + + + + - - - {tooltipData.seriesItems.map((seriesItem) => ( - - - - - - ))} - -
+ {tooltipData.axisFormattedValue} +
+
+
+ + {seriesItem.formattedLabel} + + + {seriesItem.formattedValue}
-
-
- - {seriesItem.formattedLabel} - - - {seriesItem.formattedValue} -
- - - + ))} + +
+
+ ); } diff --git a/docs/data/charts/tooltip/CustomAxisTooltip.tsx b/docs/data/charts/tooltip/CustomAxisTooltip.tsx index 010af780809f..0d0693111c49 100644 --- a/docs/data/charts/tooltip/CustomAxisTooltip.tsx +++ b/docs/data/charts/tooltip/CustomAxisTooltip.tsx @@ -1,190 +1,82 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper, { PopperProps } from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Typography from '@mui/material/Typography'; -import { useAxisTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -type PointerState = { - isActive: boolean; - isMousePointer: boolean; - pointerHeight: number; -}; - -function usePointer(): PointerState & Pick { - const svgRef = useSvgRef(); - const popperRef: PopperProps['popperRef'] = React.useRef(null); - const positionRef = React.useRef({ x: 0, y: 0 }); - - // Use a ref to avoid rerendering on every mousemove event. - const [pointer, setPointer] = React.useState({ - isActive: false, - isMousePointer: false, - pointerHeight: 0, - }); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return () => {}; - } - - const handleOut = (event: PointerEvent) => { - if (event.pointerType !== 'mouse') { - setPointer((prev) => ({ - ...prev, - isActive: false, - })); - } - }; - - const handleEnter = (event: PointerEvent) => { - setPointer({ - isActive: true, - isMousePointer: event.pointerType === 'mouse', - pointerHeight: event.height, - }); - }; - - const handleMove = (event: PointerEvent) => { - positionRef.current = { - x: event.clientX, - y: event.clientY, - }; - popperRef.current?.update(); - }; - - element.addEventListener('pointerenter', handleEnter); - element.addEventListener('pointerup', handleOut); - element.addEventListener('pointermove', handleMove); - - return () => { - element.removeEventListener('pointerenter', handleEnter); - element.removeEventListener('pointerup', handleOut); - element.removeEventListener('pointermove', handleMove); - }; - }, [svgRef]); - - return { - ...pointer, - popperRef, - anchorEl: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} +import { ChartsTooltipContainer, useAxisTooltip } from '@mui/x-charts/ChartsTooltip'; export function CustomAxisTooltip() { const tooltipData = useAxisTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { + if (!tooltipData) { // No data to display return null; } - - // The pointer type can be used to have different behavior based on pointer type. - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - + theme.zIndex.modal, - }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], + m: 1, + border: 'solid', + borderWidth: 2, + borderColor: 'divider', + table: { borderSpacing: 0 }, + thead: { + td: { + px: 1.5, + py: 0.75, + borderBottom: 'solid', + borderWidth: 2, + borderColor: 'divider', }, }, - ]} - > - - - - -
- {tooltipData.axisFormattedValue} + }, + }} + > + + + + + + + + {tooltipData.seriesItems.map((seriesItem) => ( + + + + - - - {tooltipData.seriesItems.map((seriesItem) => ( - - - - - - ))} - -
+ {tooltipData.axisFormattedValue} +
+
+
+ + {seriesItem.formattedLabel} + + + {seriesItem.formattedValue}
-
-
- - {seriesItem.formattedLabel} - - - {seriesItem.formattedValue} -
- - - + ))} + +
+
+ ); } diff --git a/docs/data/charts/tooltip/CustomItemTooltip.js b/docs/data/charts/tooltip/CustomItemTooltip.js index 2f7c2310c5d5..99ceb0dca0ff 100644 --- a/docs/data/charts/tooltip/CustomItemTooltip.js +++ b/docs/data/charts/tooltip/CustomItemTooltip.js @@ -1,144 +1,44 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; -import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -function usePointer() { - const svgRef = useSvgRef(); - const popperRef = React.useRef(null); - const positionRef = React.useRef({ x: 0, y: 0 }); - - // Use a ref to avoid rerendering on every mousemove event. - const [pointer, setPointer] = React.useState({ - isActive: false, - isMousePointer: false, - pointerHeight: 0, - }); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return () => {}; - } - - const handleOut = (event) => { - if (event.pointerType !== 'mouse') { - setPointer((prev) => ({ - ...prev, - isActive: false, - })); - } - }; - - const handleEnter = (event) => { - setPointer({ - isActive: true, - isMousePointer: event.pointerType === 'mouse', - pointerHeight: event.height, - }); - }; - - const handleMove = (event) => { - positionRef.current = { - x: event.clientX, - y: event.clientY, - }; - popperRef.current?.update(); - }; - - element.addEventListener('pointerenter', handleEnter); - element.addEventListener('pointerup', handleOut); - element.addEventListener('pointermove', handleMove); - - return () => { - element.removeEventListener('pointerenter', handleEnter); - element.removeEventListener('pointerup', handleOut); - element.removeEventListener('pointermove', handleMove); - }; - }, [svgRef]); - - return { - ...pointer, - popperRef, - anchorEl: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} +import { ChartsTooltipContainer, useItemTooltip } from '@mui/x-charts/ChartsTooltip'; export function CustomItemTooltip() { const tooltipData = useItemTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { + if (!tooltipData) { // No data to display return null; } - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - + theme.zIndex.modal, + m: 1, + p: 1.5, + border: 'solid', + borderWidth: 2, + borderColor: 'divider', }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} > - - -
- - {tooltipData.label} - - {tooltipData.formattedValue} - - - - + +
+ + {tooltipData.label} + + {tooltipData.formattedValue} + + + ); } diff --git a/docs/data/charts/tooltip/CustomItemTooltip.tsx b/docs/data/charts/tooltip/CustomItemTooltip.tsx index 077243411c5d..99ceb0dca0ff 100644 --- a/docs/data/charts/tooltip/CustomItemTooltip.tsx +++ b/docs/data/charts/tooltip/CustomItemTooltip.tsx @@ -1,150 +1,44 @@ import * as React from 'react'; -import NoSsr from '@mui/material/NoSsr'; -import Popper, { PopperProps } from '@mui/material/Popper'; import Paper from '@mui/material/Paper'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; -import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; -import { useSvgRef } from '@mui/x-charts/hooks'; - -type PointerState = { - isActive: boolean; - isMousePointer: boolean; - pointerHeight: number; -}; - -function usePointer(): PointerState & Pick { - const svgRef = useSvgRef(); - const popperRef: PopperProps['popperRef'] = React.useRef(null); - const positionRef = React.useRef({ x: 0, y: 0 }); - - // Use a ref to avoid rerendering on every mousemove event. - const [pointer, setPointer] = React.useState({ - isActive: false, - isMousePointer: false, - pointerHeight: 0, - }); - - React.useEffect(() => { - const element = svgRef.current; - if (element === null) { - return () => {}; - } - - const handleOut = (event: PointerEvent) => { - if (event.pointerType !== 'mouse') { - setPointer((prev) => ({ - ...prev, - isActive: false, - })); - } - }; - - const handleEnter = (event: PointerEvent) => { - setPointer({ - isActive: true, - isMousePointer: event.pointerType === 'mouse', - pointerHeight: event.height, - }); - }; - - const handleMove = (event: PointerEvent) => { - positionRef.current = { - x: event.clientX, - y: event.clientY, - }; - popperRef.current?.update(); - }; - - element.addEventListener('pointerenter', handleEnter); - element.addEventListener('pointerup', handleOut); - element.addEventListener('pointermove', handleMove); - - return () => { - element.removeEventListener('pointerenter', handleEnter); - element.removeEventListener('pointerup', handleOut); - element.removeEventListener('pointermove', handleMove); - }; - }, [svgRef]); - - return { - ...pointer, - popperRef, - anchorEl: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - }; -} +import { ChartsTooltipContainer, useItemTooltip } from '@mui/x-charts/ChartsTooltip'; export function CustomItemTooltip() { const tooltipData = useItemTooltip(); - const { isActive, isMousePointer, pointerHeight, popperRef, anchorEl } = - usePointer(); - if (!tooltipData || !isActive) { + if (!tooltipData) { // No data to display return null; } - // Adapt the tooltip offset to the size of the pointer. - const yOffset = isMousePointer ? 0 : 40 - pointerHeight; - return ( - - + theme.zIndex.modal, + m: 1, + p: 1.5, + border: 'solid', + borderWidth: 2, + borderColor: 'divider', }} - open - placement={isMousePointer ? 'top-end' : 'top'} - anchorEl={anchorEl} - popperRef={popperRef} - modifiers={[ - { - name: 'offset', - options: { - offset: [0, yOffset], - }, - }, - ]} > - - -
- - {tooltipData.label} - - {tooltipData.formattedValue} - - - - + +
+ + {tooltipData.label} + + {tooltipData.formattedValue} + + + ); } diff --git a/docs/data/charts/tooltip/CustomItemTooltipContent.js b/docs/data/charts/tooltip/CustomItemTooltipContent.js deleted file mode 100644 index 6cda5693841c..000000000000 --- a/docs/data/charts/tooltip/CustomItemTooltipContent.js +++ /dev/null @@ -1,37 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import Paper from '@mui/material/Paper'; - -/** - * Render a basic tooltip content for an item. - */ -export function CustomItemTooltipContent(props) { - return ( - - -
- - {props.label} - - {props.formattedValue} - - - ); -} diff --git a/docs/data/charts/tooltip/CustomItemTooltipContent.tsx b/docs/data/charts/tooltip/CustomItemTooltipContent.tsx deleted file mode 100644 index a85a7ec3fe28..000000000000 --- a/docs/data/charts/tooltip/CustomItemTooltipContent.tsx +++ /dev/null @@ -1,44 +0,0 @@ -import * as React from 'react'; -import Stack from '@mui/material/Stack'; -import Typography from '@mui/material/Typography'; -import Paper from '@mui/material/Paper'; -import { UseItemTooltipReturnValue } from '@mui/x-charts/ChartsTooltip'; -import { ChartSeriesType } from '@mui/x-charts/internals'; - -/** - * Render a basic tooltip content for an item. - */ -export function CustomItemTooltipContent( - props: Pick< - UseItemTooltipReturnValue, - 'color' | 'label' | 'formattedValue' - >, -) { - return ( - - -
- - {props.label} - - {props.formattedValue} - - - ); -} diff --git a/docs/data/charts/tooltip/CustomTooltipPosition.tsx b/docs/data/charts/tooltip/CustomTooltipPosition.tsx index 49596ca4ed65..4f0deaf7bcd5 100644 --- a/docs/data/charts/tooltip/CustomTooltipPosition.tsx +++ b/docs/data/charts/tooltip/CustomTooltipPosition.tsx @@ -9,6 +9,10 @@ import { BarPlot } from '@mui/x-charts/BarChart'; import { ChartsXAxis } from '@mui/x-charts/ChartsXAxis'; import { ChartsClipPath } from '@mui/x-charts/ChartsClipPath'; import { ChartsYAxis } from '@mui/x-charts/ChartsYAxis'; +import { + ChartsTooltipContainer, + ChartsItemTooltipContent, +} from '@mui/x-charts/ChartsTooltip'; import { ItemTooltip } from './ItemTooltip'; import { ItemTooltipFixedY } from './ItemTooltipFixedY'; import { ItemTooltipTopElement } from './ItemTooltipTopElement'; @@ -21,6 +25,14 @@ export default function CustomTooltipPosition() { const id = React.useId(); const clipPathId = `${id}-clip-path`; + + // Pick one of the custom tooltip wrapper according to the state. + const TooltipPlacement = + (tooltipType === 'mouse' && ItemTooltip) || + (tooltipType === 'fixedY' && ItemTooltipFixedY) || + (tooltipType === 'itemTop' && ItemTooltipTopElement) || + ChartsTooltipContainer; + return (
@@ -60,9 +72,11 @@ export default function CustomTooltipPosition() { - {tooltipType === 'mouse' && } - {tooltipType === 'fixedY' && } - {tooltipType === 'itemTop' && } + {/* Our custom tooltip wrapper with the default item content. */} + + + +
diff --git a/docs/data/charts/tooltip/Interaction.js b/docs/data/charts/tooltip/Interaction.js index aa9cfe094a79..d99346368b88 100644 --- a/docs/data/charts/tooltip/Interaction.js +++ b/docs/data/charts/tooltip/Interaction.js @@ -21,8 +21,8 @@ const barChartsParams = { export default function Interaction() { return ( - - + + ); } diff --git a/docs/data/charts/tooltip/Interaction.tsx b/docs/data/charts/tooltip/Interaction.tsx index cacdca34fd5a..5443660027f8 100644 --- a/docs/data/charts/tooltip/Interaction.tsx +++ b/docs/data/charts/tooltip/Interaction.tsx @@ -21,8 +21,8 @@ const barChartsParams = { export default function Interaction() { return ( - - + + ); } diff --git a/docs/data/charts/tooltip/Interaction.tsx.preview b/docs/data/charts/tooltip/Interaction.tsx.preview index dee07e073af0..09da31b473bb 100644 --- a/docs/data/charts/tooltip/Interaction.tsx.preview +++ b/docs/data/charts/tooltip/Interaction.tsx.preview @@ -1,2 +1,2 @@ - - \ No newline at end of file + + \ No newline at end of file diff --git a/docs/data/charts/tooltip/ItemTooltip.tsx b/docs/data/charts/tooltip/ItemTooltip.tsx index 1f4277d578c7..682e0e9d300b 100644 --- a/docs/data/charts/tooltip/ItemTooltip.tsx +++ b/docs/data/charts/tooltip/ItemTooltip.tsx @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper, { PopperProps } from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useSvgRef } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; type PointerState = { isActive: boolean; @@ -84,7 +83,7 @@ function usePointer(): PointerState & Pick - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx index 925b27453789..70c7bf29ec7d 100644 --- a/docs/data/charts/tooltip/ItemTooltipFixedY.tsx +++ b/docs/data/charts/tooltip/ItemTooltipFixedY.tsx @@ -3,7 +3,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper, { PopperProps } from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useDrawingArea, useSvgRef } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; type PointerState = { isActive: boolean; @@ -56,7 +55,7 @@ function usePointer(): PointerState { return pointer; } -export function ItemTooltipFixedY() { +export function ItemTooltipFixedY({ children }: React.PropsWithChildren) { const tooltipData = useItemTooltip(); const { isActive } = usePointer(); @@ -115,7 +114,7 @@ export function ItemTooltipFixedY() { }} popperRef={popperRef} > - + {children} ); diff --git a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx index 9c73fa1d4383..d3f359951d83 100644 --- a/docs/data/charts/tooltip/ItemTooltipTopElement.tsx +++ b/docs/data/charts/tooltip/ItemTooltipTopElement.tsx @@ -4,7 +4,6 @@ import NoSsr from '@mui/material/NoSsr'; import Popper from '@mui/material/Popper'; import { useItemTooltip } from '@mui/x-charts/ChartsTooltip'; import { useSvgRef, useXAxis, useXScale, useYScale } from '@mui/x-charts/hooks'; -import { CustomItemTooltipContent } from './CustomItemTooltipContent'; type PointerState = { isActive: boolean; @@ -57,7 +56,7 @@ function usePointer(): PointerState { return pointer; } -export function ItemTooltipTopElement() { +export function ItemTooltipTopElement({ children }: React.PropsWithChildren) { const tooltipData = useItemTooltip<'bar'>(); const { isActive } = usePointer(); // Get xAxis config to access its data array. @@ -123,7 +122,7 @@ export function ItemTooltipTopElement() { }), }} > - + {children} ); diff --git a/docs/data/charts/tooltip/tooltip.md b/docs/data/charts/tooltip/tooltip.md index f53171fca6e5..c7d8f10071d5 100644 --- a/docs/data/charts/tooltip/tooltip.md +++ b/docs/data/charts/tooltip/tooltip.md @@ -1,24 +1,26 @@ --- title: Charts - Tooltip productId: x-charts -components: ChartsTooltip, DefaultChartsAxisTooltipContent, DefaultChartsItemTooltipContent +components: ChartsTooltip, ChartsAxisTooltipContent, ChartsItemTooltipContent --- # Charts - Tooltip

Tooltip provides extra data on charts item.

-In all charts components, you can pass props to the tooltip by using `tooltip={{...}}`. -If you are using composition, you can add the `` component and pass props directly. +In all charts components, the tooltip is accessible via the slot `tooltip`. +If you are using composition, you can use the `` component. ## Tooltip trigger -The tooltip can be triggered by two kinds of events: +The Tooltip can be triggered by two kinds of events: - `'item'`—when the user's mouse hovers over an item on the chart, the tooltip displays data about this specific item. - `'axis'`—the user's mouse position is associated with a value of the x-axis. The tooltip displays data about all series at this specific x value. - `'none'`—disable the tooltip. +To pass this trigger attribute to the tooltip use `slotProps.tooltip.trigger`. + {{"demo": "Interaction.js"}} ## Customization @@ -90,30 +92,49 @@ It removes the header showing the x-axis value from the tooltip. ### Overriding content -To modify the tooltip content, use `slots.itemContent` or `slots.axisContent`. -The first one is rendered when tooltip trigger is set to `"item"`. -The second one when trigger is set to `"axis"`. +To override tooltip content, provide a custom component to `slots.tooltip`. +Some helper are provided, such as: + +- `` which provide a tooltip with built-in open and position management. +- `useItemTooltip()` which provides all basic information associated to the current item. +- `useAxisTooltip()` which provides all basic information associated to the current axis. + +Here is the basic scheme to follow. +Examples about helpers are provided in the composition section. ```jsx -// With single component +import { ChartsTooltipContainer } from '@mui/x-charts/ChartsTooltip'; + +function CustomItemTooltip() { + const tooltipData = useItemTooltip(); + + if (!tooltipData) { // No data to display + return null; + } + + return ( + + {/** Your custom content **/} + + ) +} + // With composition // ... - + ``` +### Overriding placement + +To override tooltip placement, override to the tooltip with `slots.tooltip`. +If you want to keep the default content, you can place the `ChartsItemTooltipContent` or `ChartsAxisTooltipContent` in your custom tooltip. + ## Composition If you're using composition, by default, the axis listens for mouse events to get its current x/y values. diff --git a/docs/data/chartsApiPages.ts b/docs/data/chartsApiPages.ts index cb5068500bfd..f089f2f0d7e1 100644 --- a/docs/data/chartsApiPages.ts +++ b/docs/data/chartsApiPages.ts @@ -55,6 +55,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-axis-highlight', title: 'ChartsAxisHighlight', }, + { + pathname: '/x/api/charts/charts-axis-tooltip-content', + title: 'ChartsAxisTooltipContent', + }, { pathname: '/x/api/charts/charts-clip-path', title: 'ChartsClipPath', @@ -63,6 +67,10 @@ const chartsApiPages: MuiPage[] = [ pathname: '/x/api/charts/charts-grid', title: 'ChartsGrid', }, + { + pathname: '/x/api/charts/charts-item-tooltip-content', + title: 'ChartsItemTooltipContent', + }, { pathname: '/x/api/charts/charts-legend', title: 'ChartsLegend', diff --git a/docs/pages/x/api/charts/bar-chart-pro.json b/docs/pages/x/api/charts/bar-chart-pro.json index 618ddf69b278..ac59b829b1e9 100644 --- a/docs/pages/x/api/charts/bar-chart-pro.json +++ b/docs/pages/x/api/charts/bar-chart-pro.json @@ -93,13 +93,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" diff --git a/docs/pages/x/api/charts/bar-chart.json b/docs/pages/x/api/charts/bar-chart.json index 802644da52d7..8c92d7728597 100644 --- a/docs/pages/x/api/charts/bar-chart.json +++ b/docs/pages/x/api/charts/bar-chart.json @@ -86,13 +86,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -173,7 +166,7 @@ "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/charts-axis-tooltip-content.js b/docs/pages/x/api/charts/charts-axis-tooltip-content.js new file mode 100644 index 000000000000..9dc6feb6568c --- /dev/null +++ b/docs/pages/x/api/charts/charts-axis-tooltip-content.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './charts-axis-tooltip-content.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/charts/charts-axis-tooltip-content', + false, + /\.\/charts-axis-tooltip-content.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/charts/charts-axis-tooltip-content.json b/docs/pages/x/api/charts/charts-axis-tooltip-content.json new file mode 100644 index 000000000000..fd3ad0ae357d --- /dev/null +++ b/docs/pages/x/api/charts/charts-axis-tooltip-content.json @@ -0,0 +1,70 @@ +{ + "props": {}, + "name": "ChartsAxisTooltipContent", + "imports": [ + "import { ChartsAxisTooltipContent } from '@mui/x-charts/ChartsTooltip';", + "import { ChartsAxisTooltipContent } from '@mui/x-charts';", + "import { ChartsAxisTooltipContent } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "cell", + "className": "MuiChartsAxisTooltipContent-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiChartsAxisTooltipContent-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiChartsAxisTooltipContent-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiChartsAxisTooltipContent-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiChartsAxisTooltipContent-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiChartsAxisTooltipContent-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiChartsAxisTooltipContent-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiChartsAxisTooltipContent-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiChartsAxisTooltipContent-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiChartsAxisTooltipContent", + "filename": "/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/charts-item-tooltip-content.js b/docs/pages/x/api/charts/charts-item-tooltip-content.js new file mode 100644 index 000000000000..3eb3dbfb139a --- /dev/null +++ b/docs/pages/x/api/charts/charts-item-tooltip-content.js @@ -0,0 +1,23 @@ +import * as React from 'react'; +import ApiPage from 'docs/src/modules/components/ApiPage'; +import mapApiPageTranslations from 'docs/src/modules/utils/mapApiPageTranslations'; +import jsonPageContent from './charts-item-tooltip-content.json'; + +export default function Page(props) { + const { descriptions, pageContent } = props; + return ; +} + +Page.getInitialProps = () => { + const req = require.context( + 'docsx/translations/api-docs/charts/charts-item-tooltip-content', + false, + /\.\/charts-item-tooltip-content.*.json$/, + ); + const descriptions = mapApiPageTranslations(req); + + return { + descriptions, + pageContent: jsonPageContent, + }; +}; diff --git a/docs/pages/x/api/charts/charts-item-tooltip-content.json b/docs/pages/x/api/charts/charts-item-tooltip-content.json new file mode 100644 index 000000000000..f54f0431bc9f --- /dev/null +++ b/docs/pages/x/api/charts/charts-item-tooltip-content.json @@ -0,0 +1,70 @@ +{ + "props": {}, + "name": "ChartsItemTooltipContent", + "imports": [ + "import { ChartsItemTooltipContent } from '@mui/x-charts/ChartsTooltip';", + "import { ChartsItemTooltipContent } from '@mui/x-charts';", + "import { ChartsItemTooltipContent } from '@mui/x-charts-pro';" + ], + "classes": [ + { + "key": "cell", + "className": "MuiChartsItemTooltipContent-cell", + "description": "Styles applied to the cell element.", + "isGlobal": false + }, + { + "key": "labelCell", + "className": "MuiChartsItemTooltipContent-labelCell", + "description": "Styles applied to the labelCell element.", + "isGlobal": false + }, + { + "key": "mark", + "className": "MuiChartsItemTooltipContent-mark", + "description": "Styles applied to the mark element.", + "isGlobal": false + }, + { + "key": "markCell", + "className": "MuiChartsItemTooltipContent-markCell", + "description": "Styles applied to the markCell element.", + "isGlobal": false + }, + { + "key": "paper", + "className": "MuiChartsItemTooltipContent-paper", + "description": "Styles applied to the paper element.", + "isGlobal": false + }, + { + "key": "root", + "className": "MuiChartsItemTooltipContent-root", + "description": "Styles applied to the root element.", + "isGlobal": false + }, + { + "key": "row", + "className": "MuiChartsItemTooltipContent-row", + "description": "Styles applied to the row element.", + "isGlobal": false + }, + { + "key": "table", + "className": "MuiChartsItemTooltipContent-table", + "description": "Styles applied to the table element.", + "isGlobal": false + }, + { + "key": "valueCell", + "className": "MuiChartsItemTooltipContent-valueCell", + "description": "Styles applied to the valueCell element.", + "isGlobal": false + } + ], + "muiName": "MuiChartsItemTooltipContent", + "filename": "/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx", + "inheritance": null, + "demos": "", + "cssComponent": false +} diff --git a/docs/pages/x/api/charts/charts-tooltip.json b/docs/pages/x/api/charts/charts-tooltip.json index 25f5895748d2..551707108abd 100644 --- a/docs/pages/x/api/charts/charts-tooltip.json +++ b/docs/pages/x/api/charts/charts-tooltip.json @@ -1,12 +1,70 @@ { "props": { + "anchorEl": { + "type": { + "name": "union", + "description": "(props, propName) => {\n if (props[propName] == null) {\n return new Error(`Prop '${propName}' is required but wasn't specified`);\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}
| func
| { contextElement?: (props, propName) => {\n if (props[propName] == null) {\n return null;\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}, getBoundingClientRect: func }" + } + }, "classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } }, + "component": { "type": { "name": "elementType" } }, + "components": { + "type": { "name": "shape", "description": "{ Root?: elementType }" }, + "default": "{}" + }, + "componentsProps": { + "type": { "name": "shape", "description": "{ root?: func
| object }" }, + "default": "{}" + }, + "container": { + "type": { + "name": "union", + "description": "(props, propName) => {\n if (props[propName] == null) {\n return new Error(`Prop '${propName}' is required but wasn't specified`);\n }\n if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) {\n return new Error(`Expected prop '${propName}' to be of type Element`);\n }\n return null;\n}
| func" + } + }, + "disablePortal": { "type": { "name": "bool" }, "default": "false" }, + "keepMounted": { "type": { "name": "bool" }, "default": "false" }, + "modifiers": { + "type": { + "name": "arrayOf", + "description": "Array<{ data?: object, effect?: func, enabled?: bool, fn?: func, name?: any, options?: object, phase?: 'afterMain'
| 'afterRead'
| 'afterWrite'
| 'beforeMain'
| 'beforeRead'
| 'beforeWrite'
| 'main'
| 'read'
| 'write', requires?: Array<string>, requiresIfExists?: Array<string> }>" + } + }, + "open": { "type": { "name": "bool" } }, + "placement": { + "type": { + "name": "enum", + "description": "'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top'" + }, + "default": "'bottom'" + }, + "popperOptions": { + "type": { + "name": "shape", + "description": "{ modifiers?: array, onFirstUpdate?: func, placement?: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', strategy?: 'absolute'
| 'fixed' }" + }, + "default": "{}" + }, + "popperRef": { + "type": { + "name": "union", + "description": "func
| { current?: { destroy: func, forceUpdate: func, setOptions: func, state: { attributes: object, elements: object, modifiersData: object, options: object, orderedModifiers: Array<object>, placement: 'auto-end'
| 'auto-start'
| 'auto'
| 'bottom-end'
| 'bottom-start'
| 'bottom'
| 'left-end'
| 'left-start'
| 'left'
| 'right-end'
| 'right-start'
| 'right'
| 'top-end'
| 'top-start'
| 'top', rects: object, reset: bool, scrollParents: object, strategy: 'absolute'
| 'fixed', styles: object }, update: func } }" + } + }, "slotProps": { "type": { "name": "object" }, "default": "{}" }, "slots": { "type": { "name": "object" }, "default": "{}", "additionalInfo": { "slotsApi": true } }, + "sx": { + "type": { + "name": "union", + "description": "Array<func
| object
| bool>
| func
| object" + }, + "additionalInfo": { "sx": true } + }, + "transition": { "type": { "name": "bool" }, "default": "false" }, "trigger": { "type": { "name": "enum", @@ -21,14 +79,6 @@ "import { ChartsTooltip } from '@mui/x-charts';", "import { ChartsTooltip } from '@mui/x-charts-pro';" ], - "slots": [ - { - "name": "popper", - "description": "Custom component for the tooltip popper.", - "default": "ChartsTooltipRoot", - "class": null - } - ], "classes": [ { "key": "cell", diff --git a/docs/pages/x/api/charts/heatmap.json b/docs/pages/x/api/charts/heatmap.json index 03ec3fbb4b44..cd3ac09b50ba 100644 --- a/docs/pages/x/api/charts/heatmap.json +++ b/docs/pages/x/api/charts/heatmap.json @@ -73,10 +73,7 @@ "additionalInfo": { "slotsApi": true } }, "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, + "type": { "name": "object" }, "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } }, "topAxis": { diff --git a/docs/pages/x/api/charts/line-chart-pro.json b/docs/pages/x/api/charts/line-chart-pro.json index 497bb7ed50f1..4a0a421935c4 100644 --- a/docs/pages/x/api/charts/line-chart-pro.json +++ b/docs/pages/x/api/charts/line-chart-pro.json @@ -86,14 +86,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" diff --git a/docs/pages/x/api/charts/line-chart.json b/docs/pages/x/api/charts/line-chart.json index 9e40563697e8..592012109bca 100644 --- a/docs/pages/x/api/charts/line-chart.json +++ b/docs/pages/x/api/charts/line-chart.json @@ -79,14 +79,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -169,7 +161,7 @@ "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/pie-chart.json b/docs/pages/x/api/charts/pie-chart.json index 947a90289044..e69991890e77 100644 --- a/docs/pages/x/api/charts/pie-chart.json +++ b/docs/pages/x/api/charts/pie-chart.json @@ -42,14 +42,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "width": { "type": { "name": "number" } }, "xAxis": { "type": { @@ -92,7 +84,7 @@ { "name": "pieArc", "description": "", "class": null }, { "name": "pieArcLabel", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/pages/x/api/charts/scatter-chart-pro.json b/docs/pages/x/api/charts/scatter-chart-pro.json index ab59187194b0..9514bb7959e2 100644 --- a/docs/pages/x/api/charts/scatter-chart-pro.json +++ b/docs/pages/x/api/charts/scatter-chart-pro.json @@ -82,14 +82,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" diff --git a/docs/pages/x/api/charts/scatter-chart.json b/docs/pages/x/api/charts/scatter-chart.json index fe249fdac396..ce2700009372 100644 --- a/docs/pages/x/api/charts/scatter-chart.json +++ b/docs/pages/x/api/charts/scatter-chart.json @@ -75,14 +75,6 @@ "default": "{}", "additionalInfo": { "slotsApi": true } }, - "tooltip": { - "type": { - "name": "shape", - "description": "{ classes?: object, slotProps?: object, slots?: object, trigger?: 'axis'
| 'item'
| 'none' }" - }, - "default": "{ trigger: 'item' }", - "seeMoreLink": { "url": "https://mui.com/x/react-charts/tooltip/", "text": "tooltip docs" } - }, "topAxis": { "type": { "name": "union", "description": "object
| string" }, "default": "null" @@ -157,13 +149,13 @@ "default": "ChartsNoDataOverlay", "class": null }, + { "name": "scatter", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null - }, - { "name": "scatter", "description": "", "class": null } + } ], "classes": [], "spread": true, diff --git a/docs/pages/x/api/charts/spark-line-chart.json b/docs/pages/x/api/charts/spark-line-chart.json index 1655d7cb0155..e6003d2ebe44 100644 --- a/docs/pages/x/api/charts/spark-line-chart.json +++ b/docs/pages/x/api/charts/spark-line-chart.json @@ -97,7 +97,7 @@ { "name": "lineHighlight", "description": "", "class": null }, { "name": "mark", "description": "", "class": null }, { - "name": "popper", + "name": "tooltip", "description": "Custom component for the tooltip popper.", "default": "ChartsTooltipRoot", "class": null diff --git a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json index 35449be42f22..efda788cfded 100644 --- a/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json +++ b/docs/translations/api-docs/charts/bar-chart-pro/bar-chart-pro.json @@ -71,10 +71,6 @@ }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, diff --git a/docs/translations/api-docs/charts/bar-chart/bar-chart.json b/docs/translations/api-docs/charts/bar-chart/bar-chart.json index 144e42200ecd..c742d35e2f76 100644 --- a/docs/translations/api-docs/charts/bar-chart/bar-chart.json +++ b/docs/translations/api-docs/charts/bar-chart/bar-chart.json @@ -67,10 +67,6 @@ }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, @@ -95,6 +91,6 @@ "legend": "Custom rendering of the legend.", "loadingOverlay": "Overlay component rendered when the chart is in a loading state.", "noDataOverlay": "Overlay component rendered when the chart has no data to display.", - "popper": "Custom component for the tooltip popper." + "tooltip": "Custom component for the tooltip popper." } } diff --git a/docs/translations/api-docs/charts/charts-axis-tooltip-content/charts-axis-tooltip-content.json b/docs/translations/api-docs/charts/charts-axis-tooltip-content/charts-axis-tooltip-content.json new file mode 100644 index 000000000000..6e845321a5fc --- /dev/null +++ b/docs/translations/api-docs/charts/charts-axis-tooltip-content/charts-axis-tooltip-content.json @@ -0,0 +1,24 @@ +{ + "componentDescription": "", + "propDescriptions": {}, + "classDescriptions": { + "cell": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the cell element" }, + "labelCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the labelCell element" + }, + "mark": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the mark element" }, + "markCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the markCell element" + }, + "paper": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the paper element" }, + "root": { "description": "Styles applied to the root element." }, + "row": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the row element" }, + "table": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the table element" }, + "valueCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the valueCell element" + } + } +} diff --git a/docs/translations/api-docs/charts/charts-item-tooltip-content/charts-item-tooltip-content.json b/docs/translations/api-docs/charts/charts-item-tooltip-content/charts-item-tooltip-content.json new file mode 100644 index 000000000000..6e845321a5fc --- /dev/null +++ b/docs/translations/api-docs/charts/charts-item-tooltip-content/charts-item-tooltip-content.json @@ -0,0 +1,24 @@ +{ + "componentDescription": "", + "propDescriptions": {}, + "classDescriptions": { + "cell": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the cell element" }, + "labelCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the labelCell element" + }, + "mark": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the mark element" }, + "markCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the markCell element" + }, + "paper": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the paper element" }, + "root": { "description": "Styles applied to the root element." }, + "row": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the row element" }, + "table": { "description": "Styles applied to {{nodeName}}.", "nodeName": "the table element" }, + "valueCell": { + "description": "Styles applied to {{nodeName}}.", + "nodeName": "the valueCell element" + } + } +} diff --git a/docs/translations/api-docs/charts/charts-tooltip/charts-tooltip.json b/docs/translations/api-docs/charts/charts-tooltip/charts-tooltip.json index 99b389364055..13d995719059 100644 --- a/docs/translations/api-docs/charts/charts-tooltip/charts-tooltip.json +++ b/docs/translations/api-docs/charts/charts-tooltip/charts-tooltip.json @@ -1,9 +1,45 @@ { "componentDescription": "", "propDescriptions": { + "anchorEl": { + "description": "An HTML element, virtualElement, or a function that returns either. It's used to set the position of the popper. The return value will passed as the reference object of the Popper instance." + }, "classes": { "description": "Override or extend the styles applied to the component." }, - "slotProps": { "description": "The props used for each component slot." }, - "slots": { "description": "Overridable component slots." }, + "component": { + "description": "The component used for the root node. Either a string to use a HTML element or a component." + }, + "components": { + "description": "The components used for each slot inside the Popper. Either a string to use a HTML element or a component." + }, + "componentsProps": { "description": "The props used for each slot inside the Popper." }, + "container": { + "description": "An HTML element or function that returns one. The container will have the portal children appended to it.
You can also provide a callback, which is called in a React layout effect. This lets you set the container from a ref, and also makes server-side rendering possible.
By default, it uses the body of the top-level document object, so it's simply document.body most of the time." + }, + "disablePortal": { + "description": "The children will be under the DOM hierarchy of the parent component." + }, + "keepMounted": { + "description": "Always keep the children in the DOM. This prop can be useful in SEO situation or when you want to maximize the responsiveness of the Popper." + }, + "modifiers": { + "description": "Popper.js is based on a "plugin-like" architecture, most of its features are fully encapsulated "modifiers".
A modifier is a function that is called each time Popper.js needs to compute the position of the popper. For this reason, modifiers should be very performant to avoid bottlenecks. To learn how to create a modifier, read the modifiers documentation." + }, + "open": { "description": "If true, the component is shown." }, + "placement": { "description": "Popper placement." }, + "popperOptions": { + "description": "Options provided to the Popper.js instance." + }, + "popperRef": { "description": "A ref that points to the used popper instance." }, + "slotProps": { "description": "The props used for each slot inside the Popper." }, + "slots": { + "description": "The components used for each slot inside the Popper. Either a string to use a HTML element or a component." + }, + "sx": { + "description": "The system prop that allows defining system overrides as well as additional CSS styles." + }, + "transition": { + "description": "Help supporting a react-transition-group/Transition component." + }, "trigger": { "description": "Select the kind of tooltip to display - 'item': Shows data about the item below the mouse. - 'axis': Shows values associated with the hovered x value - 'none': Does not display tooltip" } @@ -27,6 +63,5 @@ "description": "Styles applied to {{nodeName}}.", "nodeName": "the valueCell element" } - }, - "slotDescriptions": { "popper": "Custom component for the tooltip popper." } + } } diff --git a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json index 8e00228baa7e..2d4ab5f94e2e 100644 --- a/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json +++ b/docs/translations/api-docs/charts/line-chart-pro/line-chart-pro.json @@ -66,10 +66,6 @@ "skipAnimation": { "description": "If true, animations are skipped." }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, diff --git a/docs/translations/api-docs/charts/line-chart/line-chart.json b/docs/translations/api-docs/charts/line-chart/line-chart.json index 79b3040ce7bb..b8f5510432ad 100644 --- a/docs/translations/api-docs/charts/line-chart/line-chart.json +++ b/docs/translations/api-docs/charts/line-chart/line-chart.json @@ -62,10 +62,6 @@ "skipAnimation": { "description": "If true, animations are skipped." }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, @@ -92,6 +88,6 @@ "loadingOverlay": "Overlay component rendered when the chart is in a loading state.", "mark": "", "noDataOverlay": "Overlay component rendered when the chart has no data to display.", - "popper": "Custom component for the tooltip popper." + "tooltip": "Custom component for the tooltip popper." } } diff --git a/docs/translations/api-docs/charts/pie-chart/pie-chart.json b/docs/translations/api-docs/charts/pie-chart/pie-chart.json index 476f16fc54dd..ae1da449e83c 100644 --- a/docs/translations/api-docs/charts/pie-chart/pie-chart.json +++ b/docs/translations/api-docs/charts/pie-chart/pie-chart.json @@ -35,10 +35,6 @@ }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "width": { "description": "The width of the chart in px. If not defined, it takes the width of the parent element." }, @@ -56,6 +52,6 @@ "noDataOverlay": "Overlay component rendered when the chart has no data to display.", "pieArc": "", "pieArcLabel": "", - "popper": "Custom component for the tooltip popper." + "tooltip": "Custom component for the tooltip popper." } } diff --git a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json index d48fa62f7b10..eca50fe41f6a 100644 --- a/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json +++ b/docs/translations/api-docs/charts/scatter-chart-pro/scatter-chart-pro.json @@ -62,10 +62,6 @@ }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, diff --git a/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json b/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json index 3c022cfe4297..49295eaef91f 100644 --- a/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json +++ b/docs/translations/api-docs/charts/scatter-chart/scatter-chart.json @@ -58,10 +58,6 @@ }, "slotProps": { "description": "The props used for each component slot." }, "slots": { "description": "Overridable component slots." }, - "tooltip": { - "description": "The configuration of the tooltip.", - "seeMoreText": "See {{link}} for more details." - }, "topAxis": { "description": "Indicate which axis to display the top of the charts. Can be a string (the id of the axis) or an object ChartsXAxisProps." }, @@ -88,7 +84,7 @@ "legend": "Custom rendering of the legend.", "loadingOverlay": "Overlay component rendered when the chart is in a loading state.", "noDataOverlay": "Overlay component rendered when the chart has no data to display.", - "popper": "Custom component for the tooltip popper.", - "scatter": "" + "scatter": "", + "tooltip": "Custom component for the tooltip popper." } } diff --git a/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json b/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json index 6787bbf191e0..6a7feab5d13d 100644 --- a/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json +++ b/docs/translations/api-docs/charts/spark-line-chart/spark-line-chart.json @@ -61,6 +61,6 @@ "line": "The component that renders the line.", "lineHighlight": "", "mark": "", - "popper": "Custom component for the tooltip popper." + "tooltip": "Custom component for the tooltip popper." } } diff --git a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx index 1ea93bf6f7d1..7235cd274c46 100644 --- a/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx +++ b/packages/x-charts-pro/src/BarChartPro/BarChartPro.tsx @@ -94,10 +94,11 @@ const BarChartPro = React.forwardRef(function BarChartPro( chartsAxisProps, axisHighlightProps, legendProps, - tooltipProps, children, } = useBarChartProps(other); + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( {props.onAxisClick && } @@ -109,7 +110,7 @@ const BarChartPro = React.forwardRef(function BarChartPro( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -285,16 +286,6 @@ BarChartPro.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx index de7ee6583a82..c50b4a4b9e1f 100644 --- a/packages/x-charts-pro/src/Heatmap/Heatmap.tsx +++ b/packages/x-charts-pro/src/Heatmap/Heatmap.tsx @@ -6,11 +6,7 @@ import useId from '@mui/utils/useId'; import { MakeOptional } from '@mui/x-internals/types'; import { interpolateRgbBasis } from '@mui/x-charts-vendor/d3-interpolate'; import { ChartsAxis, ChartsAxisProps } from '@mui/x-charts/ChartsAxis'; -import { - ChartsTooltipContainerSlotProps, - ChartsTooltipContainerSlots, - ChartsTooltipProps, -} from '@mui/x-charts/ChartsTooltip'; +import { ChartsTooltipProps } from '@mui/x-charts/ChartsTooltip'; import { ChartsAxisSlots, ChartsAxisSlotProps, @@ -33,19 +29,22 @@ import { ChartContainerPro, ChartContainerProProps } from '../ChartContainerPro' import { HeatmapSeriesType } from '../models/seriesType/heatmap'; import { HeatmapPlot } from './HeatmapPlot'; import { plugin as heatmapPlugin } from './plugin'; -import { HeatmapTooltip } from './HeatmapTooltip'; +import { HeatmapTooltip, HeatmapTooltipProps } from './HeatmapTooltip'; import { HeatmapItemSlotProps, HeatmapItemSlots } from './HeatmapItem'; -export interface HeatmapSlots - extends ChartsAxisSlots, - ChartsTooltipContainerSlots, - ChartsOverlaySlots, - HeatmapItemSlots {} +export interface HeatmapSlots extends ChartsAxisSlots, ChartsOverlaySlots, HeatmapItemSlots { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface HeatmapSlotProps extends ChartsAxisSlotProps, - ChartsTooltipContainerSlotProps, ChartsOverlaySlotProps, - HeatmapItemSlotProps {} + HeatmapItemSlotProps { + tooltip?: Partial; +} export interface HeatmapProps extends Omit< @@ -159,6 +158,8 @@ const Heatmap = React.forwardRef(function Heatmap( [zAxis], ); + const Tooltip = props.slots?.tooltip ?? HeatmapTooltip; + return ( - {!loading && } + {!loading && } {children} @@ -318,12 +319,7 @@ Heatmap.propTypes = { * The configuration of the tooltip. * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), + tooltip: PropTypes.object, /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts-pro/src/Heatmap/HeatmapTooltip.tsx b/packages/x-charts-pro/src/Heatmap/HeatmapTooltip.tsx index dd5f537d58c3..2ecefa914ce3 100644 --- a/packages/x-charts-pro/src/Heatmap/HeatmapTooltip.tsx +++ b/packages/x-charts-pro/src/Heatmap/HeatmapTooltip.tsx @@ -128,20 +128,244 @@ HeatmapTooltip.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + /** + * An HTML element, [virtualElement](https://popper.js.org/docs/v2/virtual-elements/), + * or a function that returns either. + * It's used to set the position of the popper. + * The return value will passed as the reference object of the Popper instance. + */ + anchorEl: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + PropTypes.shape({ + contextElement: (props, propName) => { + if (props[propName] == null) { + return null; + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + getBoundingClientRect: PropTypes.func.isRequired, + }), + ]), /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, /** - * The props used for each component slot. + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. + * @default {} + */ + components: PropTypes.shape({ + Root: PropTypes.elementType, + }), + /** + * The props used for each slot inside the Popper. + * @default {} + */ + componentsProps: PropTypes.shape({ + root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + }), + /** + * An HTML element or function that returns one. + * The `container` will have the portal children appended to it. + * + * You can also provide a callback, which is called in a React layout effect. + * This lets you set the container from a ref, and also makes server-side rendering possible. + * + * By default, it uses the body of the top-level document object, + * so it's simply `document.body` most of the time. + */ + container: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + ]), + /** + * The `children` will be under the DOM hierarchy of the parent component. + * @default false + */ + disablePortal: PropTypes.bool, + /** + * Always keep the children in the DOM. + * This prop can be useful in SEO situation or + * when you want to maximize the responsiveness of the Popper. + * @default false + */ + keepMounted: PropTypes.bool, + /** + * Popper.js is based on a "plugin-like" architecture, + * most of its features are fully encapsulated "modifiers". + * + * A modifier is a function that is called each time Popper.js needs to + * compute the position of the popper. + * For this reason, modifiers should be very performant to avoid bottlenecks. + * To learn how to create a modifier, [read the modifiers documentation](https://popper.js.org/docs/v2/modifiers/). + */ + modifiers: PropTypes.arrayOf( + PropTypes.shape({ + data: PropTypes.object, + effect: PropTypes.func, + enabled: PropTypes.bool, + fn: PropTypes.func, + name: PropTypes.any, + options: PropTypes.object, + phase: PropTypes.oneOf([ + 'afterMain', + 'afterRead', + 'afterWrite', + 'beforeMain', + 'beforeRead', + 'beforeWrite', + 'main', + 'read', + 'write', + ]), + requires: PropTypes.arrayOf(PropTypes.string), + requiresIfExists: PropTypes.arrayOf(PropTypes.string), + }), + ), + /** + * If `true`, the component is shown. + */ + open: PropTypes.bool, + /** + * Popper placement. + * @default 'bottom' + */ + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + /** + * Options provided to the [`Popper.js`](https://popper.js.org/docs/v2/constructors/#options) instance. + * @default {} + */ + popperOptions: PropTypes.shape({ + modifiers: PropTypes.array, + onFirstUpdate: PropTypes.func, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + strategy: PropTypes.oneOf(['absolute', 'fixed']), + }), + /** + * A ref that points to the used popper instance. + */ + popperRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({ + current: PropTypes.shape({ + destroy: PropTypes.func.isRequired, + forceUpdate: PropTypes.func.isRequired, + setOptions: PropTypes.func.isRequired, + state: PropTypes.shape({ + attributes: PropTypes.object.isRequired, + elements: PropTypes.object.isRequired, + modifiersData: PropTypes.object.isRequired, + options: PropTypes.object.isRequired, + orderedModifiers: PropTypes.arrayOf(PropTypes.object).isRequired, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]).isRequired, + rects: PropTypes.object.isRequired, + reset: PropTypes.bool.isRequired, + scrollParents: PropTypes.object.isRequired, + strategy: PropTypes.oneOf(['absolute', 'fixed']).isRequired, + styles: PropTypes.object.isRequired, + }).isRequired, + update: PropTypes.func.isRequired, + }), + }), + ]), + /** + * The props used for each slot inside the Popper. * @default {} */ slotProps: PropTypes.object, /** - * Overridable component slots. + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. * @default {} */ slots: PropTypes.object, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + /** + * Help supporting a react-transition-group/Transition component. + * @default false + */ + transition: PropTypes.bool, } as any; export { HeatmapTooltip }; diff --git a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx index cd9d55b05203..c72ac72f632a 100644 --- a/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx +++ b/packages/x-charts-pro/src/LineChartPro/LineChartPro.tsx @@ -163,10 +163,11 @@ const LineChartPro = React.forwardRef(function LineChartPro( axisHighlightProps, lineHighlightPlotProps, legendProps, - tooltipProps, children, } = useLineChartProps(other); + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( {props.onAxisClick && } @@ -184,7 +185,7 @@ const LineChartPro = React.forwardRef(function LineChartPro( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -356,17 +357,6 @@ LineChartPro.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx index ee5938d7fc38..2d229851d708 100644 --- a/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx +++ b/packages/x-charts-pro/src/ScatterChartPro/ScatterChartPro.tsx @@ -44,10 +44,11 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( overlayProps, legendProps, axisHighlightProps, - tooltipProps, children, } = useScatterChartProps(other); + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( @@ -61,7 +62,7 @@ const ScatterChartPro = React.forwardRef(function ScatterChartPro( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -217,17 +218,6 @@ ScatterChartPro.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts/src/BarChart/BarChart.tsx b/packages/x-charts/src/BarChart/BarChart.tsx index b436b346a19f..f75e3369d429 100644 --- a/packages/x-charts/src/BarChart/BarChart.tsx +++ b/packages/x-charts/src/BarChart/BarChart.tsx @@ -7,12 +7,7 @@ import { BarPlot, BarPlotProps, BarPlotSlotProps, BarPlotSlots } from './BarPlot import { ChartContainer, ChartContainerProps } from '../ChartContainer'; import { ChartsAxis, ChartsAxisProps } from '../ChartsAxis'; import { BarSeriesType } from '../models/seriesType/bar'; -import { - ChartsTooltip, - ChartsTooltipProps, - ChartsTooltipSlotProps, - ChartsTooltipSlots, -} from '../ChartsTooltip'; +import { ChartsTooltip, ChartsTooltipProps } from '../ChartsTooltip'; import { ChartsLegend, ChartsLegendSlots, ChartsLegendSlotProps } from '../ChartsLegend'; import { ChartsAxisHighlight, ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { ChartsClipPath } from '../ChartsClipPath'; @@ -34,14 +29,20 @@ export interface BarChartSlots extends ChartsAxisSlots, BarPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, - ChartsOverlaySlots {} + ChartsOverlaySlots { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface BarChartSlotProps extends ChartsAxisSlotProps, BarPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, - ChartsOverlaySlotProps {} + ChartsOverlaySlotProps { + tooltip?: Partial; +} export interface BarChartProps extends Omit, @@ -54,11 +55,6 @@ export interface BarChartProps * An array of [[BarSeriesType]] objects. */ series: MakeOptional[]; - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - */ - tooltip?: ChartsTooltipProps; /** * Option to display a cartesian grid in the background. */ @@ -119,10 +115,11 @@ const BarChart = React.forwardRef(function BarChart( chartsAxisProps, axisHighlightProps, legendProps, - tooltipProps, children, } = useBarChartProps(props); + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( {props.onAxisClick && } @@ -134,7 +131,7 @@ const BarChart = React.forwardRef(function BarChart( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -303,16 +300,6 @@ BarChart.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts/src/BarChart/useBarChartProps.ts b/packages/x-charts/src/BarChart/useBarChartProps.ts index 49236b7174c7..ab65c93ad40e 100644 --- a/packages/x-charts/src/BarChart/useBarChartProps.ts +++ b/packages/x-charts/src/BarChart/useBarChartProps.ts @@ -11,7 +11,6 @@ import { ChartsOverlayProps } from '../ChartsOverlay'; import { ChartsAxisProps } from '../ChartsAxis'; import { ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { ChartsLegendProps } from '../ChartsLegend'; -import { ChartsTooltipProps } from '../ChartsTooltip'; /** * A helper function that extracts BarChartProps from the input props @@ -31,7 +30,6 @@ export const useBarChartProps = (props: BarChartProps) => { colors, dataset, sx, - tooltip, onAxisClick, axisHighlight, grid, @@ -92,7 +90,7 @@ export const useBarChartProps = (props: BarChartProps) => { highlightedItem, onHighlightChange, disableAxisListener: - tooltip?.trigger !== 'axis' && + slotProps?.tooltip?.trigger !== 'axis' && axisHighlight?.x === 'none' && axisHighlight?.y === 'none' && !onAxisClick, @@ -150,12 +148,6 @@ export const useBarChartProps = (props: BarChartProps) => { slotProps, }; - const tooltipProps: ChartsTooltipProps = { - ...tooltip, - slots, - slotProps, - }; - return { chartContainerProps, barPlotProps, @@ -167,7 +159,6 @@ export const useBarChartProps = (props: BarChartProps) => { chartsAxisProps, axisHighlightProps, legendProps, - tooltipProps, children, }; }; diff --git a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx index 3f8f23fcdc8b..877aa260b312 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsAxisTooltipContent.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import { SxProps, Theme } from '@mui/material/styles'; import Typography from '@mui/material/Typography'; import clsx from 'clsx'; -import { ChartsTooltipClasses } from './chartsTooltipClasses'; +import { ChartsTooltipClasses, useUtilityClasses } from './chartsTooltipClasses'; import { ChartsTooltipCell, ChartsTooltipMark, @@ -21,18 +21,17 @@ export type ChartsAxisContentProps = { sx?: SxProps; }; -/** - * @ignore - internal component. - */ function ChartsAxisTooltipContent(props: { sx?: SxProps; classes: ChartsAxisContentProps['classes']; }) { - const { classes, sx } = props; + const { classes: propClasses, sx } = props; const tootlipData = useAxisTooltip(); const xAxis = useXAxis(); const yAxis = useYAxis(); + const classes = useUtilityClasses(propClasses); + if (tootlipData === null) { return null; } diff --git a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx index d8ff37e413e9..e48353319991 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsItemTooltipContent.tsx @@ -1,7 +1,7 @@ import * as React from 'react'; import clsx from 'clsx'; import { SxProps, Theme } from '@mui/material/styles'; -import { ChartsTooltipClasses } from './chartsTooltipClasses'; +import { ChartsTooltipClasses, useUtilityClasses } from './chartsTooltipClasses'; import { useItemTooltip } from './useItemTooltip'; import { ChartsTooltipCell, @@ -13,20 +13,18 @@ import { export interface ChartsItemTooltipContentProps { sx?: SxProps; - classes: ChartsTooltipClasses; + classes?: ChartsTooltipClasses; } -/** - * @ignore - internal component. - */ function ChartsItemTooltipContent(props: ChartsItemTooltipContentProps) { - const { classes, sx } = props; + const { classes: propClasses, sx } = props; const tooltipData = useItemTooltip(); + const classes = useUtilityClasses(propClasses); + if (!tooltipData) { return null; } - const { color, label, formattedValue } = tooltipData; return ( diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx b/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx index 01b197970b90..6173a3f6bd2f 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltip.tsx @@ -1,38 +1,12 @@ 'use client'; import * as React from 'react'; import PropTypes from 'prop-types'; -import composeClasses from '@mui/utils/composeClasses'; import { ChartsItemTooltipContent } from './ChartsItemTooltipContent'; import { ChartsAxisTooltipContent } from './ChartsAxisTooltipContent'; -import { getChartsTooltipUtilityClass } from './chartsTooltipClasses'; -import { - ChartsTooltipContainer, - ChartsTooltipContainerProps, - ChartsTooltipContainerSlotProps, - ChartsTooltipContainerSlots, -} from './ChartsTooltipContainer'; +import { ChartsTooltipContainer, ChartsTooltipContainerProps } from './ChartsTooltipContainer'; +import { useUtilityClasses } from './chartsTooltipClasses'; export interface ChartsTooltipProps extends Omit {} -export interface ChartsTooltipSlotProps extends ChartsTooltipContainerSlotProps {} -export interface ChartsTooltipSlots extends ChartsTooltipContainerSlots {} - -const useUtilityClasses = (ownerState: { classes: ChartsTooltipProps['classes'] }) => { - const { classes } = ownerState; - - const slots = { - root: ['root'], - paper: ['paper'], - table: ['table'], - row: ['row'], - cell: ['cell'], - mark: ['mark'], - markCell: ['markCell'], - labelCell: ['labelCell'], - valueCell: ['valueCell'], - }; - - return composeClasses(slots, getChartsTooltipUtilityClass, classes); -}; /** * Demos: @@ -46,7 +20,7 @@ const useUtilityClasses = (ownerState: { classes: ChartsTooltipProps['classes'] function ChartsTooltip(props: ChartsTooltipProps) { const { classes: propClasses, trigger = 'axis' } = props; - const classes = useUtilityClasses({ classes: propClasses }); + const classes = useUtilityClasses(propClasses); return ( @@ -64,20 +38,244 @@ ChartsTooltip.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + /** + * An HTML element, [virtualElement](https://popper.js.org/docs/v2/virtual-elements/), + * or a function that returns either. + * It's used to set the position of the popper. + * The return value will passed as the reference object of the Popper instance. + */ + anchorEl: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + PropTypes.shape({ + contextElement: (props, propName) => { + if (props[propName] == null) { + return null; + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + getBoundingClientRect: PropTypes.func.isRequired, + }), + ]), /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, /** - * The props used for each component slot. + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. + * @default {} + */ + components: PropTypes.shape({ + Root: PropTypes.elementType, + }), + /** + * The props used for each slot inside the Popper. + * @default {} + */ + componentsProps: PropTypes.shape({ + root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + }), + /** + * An HTML element or function that returns one. + * The `container` will have the portal children appended to it. + * + * You can also provide a callback, which is called in a React layout effect. + * This lets you set the container from a ref, and also makes server-side rendering possible. + * + * By default, it uses the body of the top-level document object, + * so it's simply `document.body` most of the time. + */ + container: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + ]), + /** + * The `children` will be under the DOM hierarchy of the parent component. + * @default false + */ + disablePortal: PropTypes.bool, + /** + * Always keep the children in the DOM. + * This prop can be useful in SEO situation or + * when you want to maximize the responsiveness of the Popper. + * @default false + */ + keepMounted: PropTypes.bool, + /** + * Popper.js is based on a "plugin-like" architecture, + * most of its features are fully encapsulated "modifiers". + * + * A modifier is a function that is called each time Popper.js needs to + * compute the position of the popper. + * For this reason, modifiers should be very performant to avoid bottlenecks. + * To learn how to create a modifier, [read the modifiers documentation](https://popper.js.org/docs/v2/modifiers/). + */ + modifiers: PropTypes.arrayOf( + PropTypes.shape({ + data: PropTypes.object, + effect: PropTypes.func, + enabled: PropTypes.bool, + fn: PropTypes.func, + name: PropTypes.any, + options: PropTypes.object, + phase: PropTypes.oneOf([ + 'afterMain', + 'afterRead', + 'afterWrite', + 'beforeMain', + 'beforeRead', + 'beforeWrite', + 'main', + 'read', + 'write', + ]), + requires: PropTypes.arrayOf(PropTypes.string), + requiresIfExists: PropTypes.arrayOf(PropTypes.string), + }), + ), + /** + * If `true`, the component is shown. + */ + open: PropTypes.bool, + /** + * Popper placement. + * @default 'bottom' + */ + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + /** + * Options provided to the [`Popper.js`](https://popper.js.org/docs/v2/constructors/#options) instance. + * @default {} + */ + popperOptions: PropTypes.shape({ + modifiers: PropTypes.array, + onFirstUpdate: PropTypes.func, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + strategy: PropTypes.oneOf(['absolute', 'fixed']), + }), + /** + * A ref that points to the used popper instance. + */ + popperRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({ + current: PropTypes.shape({ + destroy: PropTypes.func.isRequired, + forceUpdate: PropTypes.func.isRequired, + setOptions: PropTypes.func.isRequired, + state: PropTypes.shape({ + attributes: PropTypes.object.isRequired, + elements: PropTypes.object.isRequired, + modifiersData: PropTypes.object.isRequired, + options: PropTypes.object.isRequired, + orderedModifiers: PropTypes.arrayOf(PropTypes.object).isRequired, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]).isRequired, + rects: PropTypes.object.isRequired, + reset: PropTypes.bool.isRequired, + scrollParents: PropTypes.object.isRequired, + strategy: PropTypes.oneOf(['absolute', 'fixed']).isRequired, + styles: PropTypes.object.isRequired, + }).isRequired, + update: PropTypes.func.isRequired, + }), + }), + ]), + /** + * The props used for each slot inside the Popper. * @default {} */ slotProps: PropTypes.object, /** - * Overridable component slots. + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. * @default {} */ slots: PropTypes.object, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + /** + * Help supporting a react-transition-group/Transition component. + * @default false + */ + transition: PropTypes.bool, /** * Select the kind of tooltip to display * - 'item': Shows data about the item below the mouse. diff --git a/packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx b/packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx index 0b540bd77b5f..3fcfa1f9234e 100644 --- a/packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx +++ b/packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx @@ -2,10 +2,9 @@ import * as React from 'react'; import PropTypes from 'prop-types'; import useLazyRef from '@mui/utils/useLazyRef'; -import { styled, useThemeProps, SxProps, Theme } from '@mui/material/styles'; -import Popper, { PopperProps as BasePopperProps } from '@mui/material/Popper'; +import { styled, useThemeProps } from '@mui/material/styles'; +import Popper, { PopperProps } from '@mui/material/Popper'; import NoSsr from '@mui/material/NoSsr'; -import useSlotProps from '@mui/utils/useSlotProps'; import { useSvgRef } from '../hooks/useSvgRef'; import { TriggerOptions, usePointerType } from './utils'; import { ChartsTooltipClasses } from './chartsTooltipClasses'; @@ -18,26 +17,7 @@ import { selectorChartsInteractionYAxisIsDefined, } from '../context/InteractionSelectors'; -export type PopperProps = BasePopperProps & { - /** - * The system prop that allows defining system overrides as well as additional CSS styles. - */ - sx?: SxProps; -}; - -export interface ChartsTooltipContainerSlots { - /** - * Custom component for the tooltip popper. - * @default ChartsTooltipRoot - */ - popper?: React.ElementType; -} - -export interface ChartsTooltipContainerSlotProps { - popper?: Partial; -} - -export interface ChartsTooltipContainerProps { +export interface ChartsTooltipContainerProps extends Partial { /** * Select the kind of tooltip to display * - 'item': Shows data about the item below the mouse. @@ -50,16 +30,6 @@ export interface ChartsTooltipContainerProps { * Override or extend the styles applied to the component. */ classes?: Partial; - /** - * Overridable component slots. - * @default {} - */ - slots?: ChartsTooltipContainerSlots; - /** - * The props used for each component slot. - * @default {} - */ - slotProps?: ChartsTooltipContainerSlotProps; children?: React.ReactNode; } @@ -86,7 +56,7 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) { props: inProps, name: 'MuiChartsTooltipContainer', }); - const { trigger = 'axis', slots, slotProps, classes, children } = props; + const { trigger = 'axis', classes, children, ...other } = props; const svgRef = useSvgRef(); const pointerType = usePointerType(); @@ -110,41 +80,6 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) { const popperOpen = pointerType !== null && isOpen; // tooltipHasData; - const PopperComponent = slots?.popper ?? ChartsTooltipRoot; - - const popperProps = useSlotProps({ - elementType: PopperComponent, - externalSlotProps: slotProps?.popper, - className: classes?.root, - additionalProps: { - open: popperOpen, - placement: pointerType?.pointerType === 'mouse' ? ('right-start' as const) : ('top' as const), - popperRef, - anchorEl: { - getBoundingClientRect: () => ({ - x: positionRef.current.x, - y: positionRef.current.y, - top: positionRef.current.y, - left: positionRef.current.x, - right: positionRef.current.x, - bottom: positionRef.current.y, - width: 0, - height: 0, - toJSON: () => '', - }), - }, - modifiers: [ - { - name: 'offset', - options: { - offset: [0, pointerType?.pointerType === 'touch' ? 40 - pointerType.height : 0], - }, - }, - ], - }, - ownerState: {}, - }); - React.useEffect(() => { const element = svgRef.current; if (element === null) { @@ -168,7 +103,42 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) { } return ( - {popperOpen && {children}} + + {popperOpen && ( + ({ + x: positionRef.current.x, + y: positionRef.current.y, + top: positionRef.current.y, + left: positionRef.current.x, + right: positionRef.current.x, + bottom: positionRef.current.y, + width: 0, + height: 0, + toJSON: () => '', + }), + }} + modifiers={[ + { + name: 'offset', + options: { + offset: [0, pointerType?.pointerType === 'touch' ? 40 - pointerType.height : 0], + }, + }, + ]} + {...other} + > + {children} + + )} + ); } @@ -177,21 +147,248 @@ ChartsTooltipContainer.propTypes = { // | These PropTypes are generated from the TypeScript type definitions | // | To update them edit the TypeScript types and run "pnpm proptypes" | // ---------------------------------------------------------------------- + /** + * An HTML element, [virtualElement](https://popper.js.org/docs/v2/virtual-elements/), + * or a function that returns either. + * It's used to set the position of the popper. + * The return value will passed as the reference object of the Popper instance. + */ + anchorEl: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + PropTypes.shape({ + contextElement: (props, propName) => { + if (props[propName] == null) { + return null; + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + getBoundingClientRect: PropTypes.func.isRequired, + }), + ]), + /** + * Popper render function or node. + */ children: PropTypes.node, /** * Override or extend the styles applied to the component. */ classes: PropTypes.object, /** - * The props used for each component slot. + * The component used for the root node. + * Either a string to use a HTML element or a component. + */ + component: PropTypes.elementType, + /** + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. + * @default {} + */ + components: PropTypes.shape({ + Root: PropTypes.elementType, + }), + /** + * The props used for each slot inside the Popper. + * @default {} + */ + componentsProps: PropTypes.shape({ + root: PropTypes.oneOfType([PropTypes.func, PropTypes.object]), + }), + /** + * An HTML element or function that returns one. + * The `container` will have the portal children appended to it. + * + * You can also provide a callback, which is called in a React layout effect. + * This lets you set the container from a ref, and also makes server-side rendering possible. + * + * By default, it uses the body of the top-level document object, + * so it's simply `document.body` most of the time. + */ + container: PropTypes.oneOfType([ + (props, propName) => { + if (props[propName] == null) { + return new Error(`Prop '${propName}' is required but wasn't specified`); + } + if (typeof props[propName] !== 'object' || props[propName].nodeType !== 1) { + return new Error(`Expected prop '${propName}' to be of type Element`); + } + return null; + }, + PropTypes.func, + ]), + /** + * The `children` will be under the DOM hierarchy of the parent component. + * @default false + */ + disablePortal: PropTypes.bool, + /** + * Always keep the children in the DOM. + * This prop can be useful in SEO situation or + * when you want to maximize the responsiveness of the Popper. + * @default false + */ + keepMounted: PropTypes.bool, + /** + * Popper.js is based on a "plugin-like" architecture, + * most of its features are fully encapsulated "modifiers". + * + * A modifier is a function that is called each time Popper.js needs to + * compute the position of the popper. + * For this reason, modifiers should be very performant to avoid bottlenecks. + * To learn how to create a modifier, [read the modifiers documentation](https://popper.js.org/docs/v2/modifiers/). + */ + modifiers: PropTypes.arrayOf( + PropTypes.shape({ + data: PropTypes.object, + effect: PropTypes.func, + enabled: PropTypes.bool, + fn: PropTypes.func, + name: PropTypes.any, + options: PropTypes.object, + phase: PropTypes.oneOf([ + 'afterMain', + 'afterRead', + 'afterWrite', + 'beforeMain', + 'beforeRead', + 'beforeWrite', + 'main', + 'read', + 'write', + ]), + requires: PropTypes.arrayOf(PropTypes.string), + requiresIfExists: PropTypes.arrayOf(PropTypes.string), + }), + ), + /** + * If `true`, the component is shown. + */ + open: PropTypes.bool, + /** + * Popper placement. + * @default 'bottom' + */ + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + /** + * Options provided to the [`Popper.js`](https://popper.js.org/docs/v2/constructors/#options) instance. + * @default {} + */ + popperOptions: PropTypes.shape({ + modifiers: PropTypes.array, + onFirstUpdate: PropTypes.func, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]), + strategy: PropTypes.oneOf(['absolute', 'fixed']), + }), + /** + * A ref that points to the used popper instance. + */ + popperRef: PropTypes.oneOfType([ + PropTypes.func, + PropTypes.shape({ + current: PropTypes.shape({ + destroy: PropTypes.func.isRequired, + forceUpdate: PropTypes.func.isRequired, + setOptions: PropTypes.func.isRequired, + state: PropTypes.shape({ + attributes: PropTypes.object.isRequired, + elements: PropTypes.object.isRequired, + modifiersData: PropTypes.object.isRequired, + options: PropTypes.object.isRequired, + orderedModifiers: PropTypes.arrayOf(PropTypes.object).isRequired, + placement: PropTypes.oneOf([ + 'auto-end', + 'auto-start', + 'auto', + 'bottom-end', + 'bottom-start', + 'bottom', + 'left-end', + 'left-start', + 'left', + 'right-end', + 'right-start', + 'right', + 'top-end', + 'top-start', + 'top', + ]).isRequired, + rects: PropTypes.object.isRequired, + reset: PropTypes.bool.isRequired, + scrollParents: PropTypes.object.isRequired, + strategy: PropTypes.oneOf(['absolute', 'fixed']).isRequired, + styles: PropTypes.object.isRequired, + }).isRequired, + update: PropTypes.func.isRequired, + }), + }), + ]), + /** + * The props used for each slot inside the Popper. * @default {} */ slotProps: PropTypes.object, /** - * Overridable component slots. + * The components used for each slot inside the Popper. + * Either a string to use a HTML element or a component. * @default {} */ slots: PropTypes.object, + /** + * The system prop that allows defining system overrides as well as additional CSS styles. + */ + sx: PropTypes.oneOfType([ + PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.func, PropTypes.object, PropTypes.bool])), + PropTypes.func, + PropTypes.object, + ]), + /** + * Help supporting a react-transition-group/Transition component. + * @default false + */ + transition: PropTypes.bool, /** * Select the kind of tooltip to display * - 'item': Shows data about the item below the mouse. diff --git a/packages/x-charts/src/ChartsTooltip/chartsTooltipClasses.ts b/packages/x-charts/src/ChartsTooltip/chartsTooltipClasses.ts index b4ada8e0254b..ca48ae98be11 100644 --- a/packages/x-charts/src/ChartsTooltip/chartsTooltipClasses.ts +++ b/packages/x-charts/src/ChartsTooltip/chartsTooltipClasses.ts @@ -1,7 +1,6 @@ -import { - unstable_generateUtilityClass as generateUtilityClass, - unstable_generateUtilityClasses as generateUtilityClasses, -} from '@mui/utils'; +import generateUtilityClass from '@mui/utils/generateUtilityClass'; +import generateUtilityClasses from '@mui/utils/generateUtilityClasses'; +import composeClasses from '@mui/utils/composeClasses'; export interface ChartsTooltipClasses { /** Styles applied to the root element. */ @@ -37,3 +36,19 @@ export const chartsTooltipClasses: ChartsTooltipClasses = generateUtilityClasses 'MuiChartsTooltip', ['root', 'paper', 'table', 'row', 'cell', 'mark', 'markCell', 'labelCell', 'valueCell'], ); + +export const useUtilityClasses = (classes?: Partial) => { + const slots = { + root: ['root'], + paper: ['paper'], + table: ['table'], + row: ['row'], + cell: ['cell'], + mark: ['mark'], + markCell: ['markCell'], + labelCell: ['labelCell'], + valueCell: ['valueCell'], + }; + + return composeClasses(slots, getChartsTooltipUtilityClass, classes); +}; diff --git a/packages/x-charts/src/ChartsTooltip/contentDisplayed.test.tsx b/packages/x-charts/src/ChartsTooltip/contentDisplayed.test.tsx index bde48ebc9f35..2fa0ee4139b3 100644 --- a/packages/x-charts/src/ChartsTooltip/contentDisplayed.test.tsx +++ b/packages/x-charts/src/ChartsTooltip/contentDisplayed.test.tsx @@ -184,7 +184,7 @@ describe('ChartsTooltip', () => { { dataKey: 'v2', id: 's2', label: 'S2' }, ]} xAxis={[{ scaleType: 'band', dataKey: 'x' }]} - tooltip={{ trigger: 'item' }} + slotProps={{ tooltip: { trigger: 'item' } }} />
, ); @@ -229,7 +229,7 @@ describe('ChartsTooltip', () => { ]} layout="horizontal" yAxis={[{ scaleType: 'band', dataKey: 'x' }]} - tooltip={{ trigger: 'item' }} + slotProps={{ tooltip: { trigger: 'item' } }} />
, ); diff --git a/packages/x-charts/src/ChartsTooltip/index.ts b/packages/x-charts/src/ChartsTooltip/index.ts index b8127234a18f..dabbfdc28d80 100644 --- a/packages/x-charts/src/ChartsTooltip/index.ts +++ b/packages/x-charts/src/ChartsTooltip/index.ts @@ -1,6 +1,11 @@ export * from './ChartsTooltip'; export * from './ChartsTooltipContainer'; -export * from './chartsTooltipClasses'; +export { + ChartsTooltipClasses, + ChartsTooltipClassKey, + getChartsTooltipUtilityClass, + chartsTooltipClasses, +} from './chartsTooltipClasses'; export * from './ChartsAxisTooltipContent'; export * from './ChartsItemTooltipContent'; diff --git a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx index 85b20f645a5a..db59be675cc4 100644 --- a/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx +++ b/packages/x-charts/src/ChartsTooltip/useItemTooltip.tsx @@ -1,6 +1,6 @@ 'use client'; import * as React from 'react'; -import { ItemInteractionData, useStore } from '../context/InteractionProvider'; +import { ItemInteractionData } from '../context/InteractionProvider'; import { useSeries } from '../hooks/useSeries'; import { useCartesianContext } from '../context/CartesianProvider'; import { ZAxisContext } from '../context/ZAxisContextProvider'; @@ -14,6 +14,7 @@ import { getLabel } from '../internals/getLabel'; import { CommonSeriesType } from '../models/seriesType/common'; import { useSelector } from '../internals/useSelector'; import { selectorChartsInteractionItem } from '../context/InteractionSelectors'; +import { useStore } from '../internals/useStore'; export interface UseItemTooltipReturnValue { identifier: ItemInteractionData; diff --git a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx index 57bb56d557d0..dfdafbd93a6b 100644 --- a/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx +++ b/packages/x-charts/src/ChartsVoronoiHandler/ChartsVoronoiHandler.tsx @@ -9,8 +9,9 @@ import { getSVGPoint } from '../internals/getSVGPoint'; import { ScatterItemIdentifier } from '../models'; import { SeriesId } from '../models/seriesType/common'; import { useDrawingArea, useSvgRef } from '../hooks'; -import { useHighlighted, useStore } from '../context'; +import { useHighlighted } from '../context'; import { useScatterSeries } from '../hooks/useSeries'; +import { useStore } from '../internals/useStore'; export type ChartsVoronoiHandlerProps = { /** diff --git a/packages/x-charts/src/LineChart/CircleMarkElement.tsx b/packages/x-charts/src/LineChart/CircleMarkElement.tsx index 2a14511f2472..75caf10d3f58 100644 --- a/packages/x-charts/src/LineChart/CircleMarkElement.tsx +++ b/packages/x-charts/src/LineChart/CircleMarkElement.tsx @@ -5,10 +5,11 @@ import { useTheme } from '@mui/material/styles'; import { warnOnce } from '@mui/x-internals/warning'; import { animated, useSpring } from '@react-spring/web'; import { useInteractionItemProps } from '../hooks/useInteractionItemProps'; -import { useItemHighlighted, useStore } from '../context'; +import { useItemHighlighted } from '../context'; import { MarkElementOwnerState, useUtilityClasses } from './markElementClasses'; import { useSelector } from '../internals/useSelector'; import { selectorChartsInteractionXAxis } from '../context/InteractionSelectors'; +import { useStore } from '../internals/useStore'; export type CircleMarkElementProps = Omit & Omit, 'ref' | 'id'> & { diff --git a/packages/x-charts/src/LineChart/LineChart.tsx b/packages/x-charts/src/LineChart/LineChart.tsx index a815d8cafa71..b55f6d44f2f3 100644 --- a/packages/x-charts/src/LineChart/LineChart.tsx +++ b/packages/x-charts/src/LineChart/LineChart.tsx @@ -9,12 +9,7 @@ import { ChartContainer, ChartContainerProps } from '../ChartContainer'; import { MarkPlot, MarkPlotProps, MarkPlotSlotProps, MarkPlotSlots } from './MarkPlot'; import { ChartsAxis, ChartsAxisProps } from '../ChartsAxis/ChartsAxis'; import { LineSeriesType } from '../models/seriesType/line'; -import { - ChartsTooltip, - ChartsTooltipProps, - ChartsTooltipSlotProps, - ChartsTooltipSlots, -} from '../ChartsTooltip'; +import { ChartsTooltip, ChartsTooltipProps } from '../ChartsTooltip'; import { ChartsLegend, ChartsLegendSlotProps, ChartsLegendSlots } from '../ChartsLegend'; import { ChartsAxisHighlight, ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { ChartsClipPath } from '../ChartsClipPath'; @@ -44,8 +39,13 @@ export interface LineChartSlots MarkPlotSlots, LineHighlightPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, - ChartsOverlaySlots {} + ChartsOverlaySlots { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface LineChartSlotProps extends ChartsAxisSlotProps, AreaPlotSlotProps, @@ -53,8 +53,9 @@ export interface LineChartSlotProps MarkPlotSlotProps, LineHighlightPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, - ChartsOverlaySlotProps {} + ChartsOverlaySlotProps { + tooltip?: Partial; +} export interface LineChartProps extends Omit, @@ -66,12 +67,6 @@ export interface LineChartProps * An array of [[LineSeriesType]] objects. */ series: MakeOptional[]; - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip?: ChartsTooltipProps; /** * Option to display a cartesian grid in the background. */ @@ -152,10 +147,11 @@ const LineChart = React.forwardRef(function LineChart( axisHighlightProps, lineHighlightPlotProps, legendProps, - tooltipProps, children, } = useLineChartProps(props); + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( {props.onAxisClick && } @@ -173,7 +169,7 @@ const LineChart = React.forwardRef(function LineChart( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -338,17 +334,6 @@ LineChart.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts/src/LineChart/useLineChartProps.ts b/packages/x-charts/src/LineChart/useLineChartProps.ts index bf4114395305..05cef6fc627b 100644 --- a/packages/x-charts/src/LineChart/useLineChartProps.ts +++ b/packages/x-charts/src/LineChart/useLineChartProps.ts @@ -7,7 +7,6 @@ import { ChartsGridProps } from '../ChartsGrid'; import { ChartsLegendProps } from '../ChartsLegend'; import { ChartsOnAxisClickHandlerProps } from '../ChartsOnAxisClickHandler'; import { ChartsOverlayProps } from '../ChartsOverlay'; -import { ChartsTooltipProps } from '../ChartsTooltip'; import { DEFAULT_X_AXIS_KEY } from '../constants'; import { ChartContainerProps } from '../ChartContainer'; import { AreaPlotProps } from './AreaPlot'; @@ -34,7 +33,6 @@ export const useLineChartProps = (props: LineChartProps) => { colors, dataset, sx, - tooltip, onAxisClick, onAreaClick, onLineClick, @@ -89,7 +87,7 @@ export const useLineChartProps = (props: LineChartProps) => { highlightedItem, onHighlightChange, disableAxisListener: - tooltip?.trigger !== 'axis' && + slotProps?.tooltip?.trigger !== 'axis' && axisHighlight?.x === 'none' && axisHighlight?.y === 'none' && !onAxisClick, @@ -164,12 +162,6 @@ export const useLineChartProps = (props: LineChartProps) => { slotProps, }; - const tooltipProps: ChartsTooltipProps = { - ...tooltip, - slots, - slotProps, - }; - return { chartContainerProps, axisClickHandlerProps, @@ -184,7 +176,6 @@ export const useLineChartProps = (props: LineChartProps) => { axisHighlightProps, lineHighlightPlotProps, legendProps, - tooltipProps, children, }; }; diff --git a/packages/x-charts/src/PieChart/PieChart.tsx b/packages/x-charts/src/PieChart/PieChart.tsx index 203ab334bd1c..44ec45bbb228 100644 --- a/packages/x-charts/src/PieChart/PieChart.tsx +++ b/packages/x-charts/src/PieChart/PieChart.tsx @@ -6,12 +6,7 @@ import { useThemeProps } from '@mui/material/styles'; import { MakeOptional } from '@mui/x-internals/types'; import { ChartContainer, ChartContainerProps } from '../ChartContainer'; import { PieSeriesType } from '../models/seriesType'; -import { - ChartsTooltip, - ChartsTooltipProps, - ChartsTooltipSlotProps, - ChartsTooltipSlots, -} from '../ChartsTooltip'; +import { ChartsTooltip, ChartsTooltipProps } from '../ChartsTooltip'; import { ChartsLegend, ChartsLegendSlotProps, ChartsLegendSlots } from '../ChartsLegend'; import { PiePlot, PiePlotProps, PiePlotSlotProps, PiePlotSlots } from './PiePlot'; import { PieValueType } from '../models/seriesType/pie'; @@ -22,17 +17,20 @@ import { ChartsOverlaySlots, } from '../ChartsOverlay'; -export interface PieChartSlots - extends PiePlotSlots, - ChartsLegendSlots, - ChartsTooltipSlots, - ChartsOverlaySlots {} +export interface PieChartSlots extends PiePlotSlots, ChartsLegendSlots, ChartsOverlaySlots { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface PieChartSlotProps extends PiePlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, - ChartsOverlaySlotProps {} + ChartsOverlaySlotProps { + tooltip?: Partial; +} export interface PieChartProps extends Omit, @@ -43,12 +41,6 @@ export interface PieChartProps * An array of [[PieSeriesType]] objects. */ series: MakeOptional>, 'type'>[]; - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip?: ChartsTooltipProps; /** * If `true`, the legend is not rendered. */ @@ -96,7 +88,6 @@ const PieChart = React.forwardRef(function PieChart( margin: marginProps, colors, sx, - tooltip = { trigger: 'item' }, skipAnimation, hideLegend, children, @@ -113,6 +104,7 @@ const PieChart = React.forwardRef(function PieChart( const margin = { ...(isRtl ? defaultRTLMargin : defaultMargin), ...marginProps }; + const Tooltip = slots?.tooltip ?? ChartsTooltip; return ( )} - {!loading && } + {!loading && } {children} ); @@ -246,17 +238,6 @@ PieChart.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), viewBox: PropTypes.shape({ height: PropTypes.number, width: PropTypes.number, diff --git a/packages/x-charts/src/ScatterChart/ScatterChart.tsx b/packages/x-charts/src/ScatterChart/ScatterChart.tsx index ed8e22632c6c..f33839403563 100644 --- a/packages/x-charts/src/ScatterChart/ScatterChart.tsx +++ b/packages/x-charts/src/ScatterChart/ScatterChart.tsx @@ -12,12 +12,7 @@ import { import { ChartContainer, ChartContainerProps } from '../ChartContainer'; import { ChartsAxis, ChartsAxisProps } from '../ChartsAxis'; import { ScatterSeriesType } from '../models/seriesType/scatter'; -import { - ChartsTooltip, - ChartsTooltipProps, - ChartsTooltipSlotProps, - ChartsTooltipSlots, -} from '../ChartsTooltip'; +import { ChartsTooltip, ChartsTooltipProps } from '../ChartsTooltip'; import { ChartsLegend, ChartsLegendSlotProps, ChartsLegendSlots } from '../ChartsLegend'; import { ChartsOverlay, @@ -39,14 +34,20 @@ export interface ScatterChartSlots extends ChartsAxisSlots, ScatterPlotSlots, ChartsLegendSlots, - ChartsTooltipSlots, - ChartsOverlaySlots {} + ChartsOverlaySlots { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface ScatterChartSlotProps extends ChartsAxisSlotProps, ScatterPlotSlotProps, ChartsLegendSlotProps, - ChartsTooltipSlotProps, - ChartsOverlaySlotProps {} + ChartsOverlaySlotProps { + tooltip?: Partial; +} export interface ScatterChartProps extends Omit, @@ -59,12 +60,6 @@ export interface ScatterChartProps * An array of [[ScatterSeriesType]] objects. */ series: MakeOptional[]; - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip?: ChartsTooltipProps; /** * The configuration of axes highlight. * @see See {@link https://mui.com/x/react-charts/highlighting highlighting docs} for more details. @@ -127,9 +122,11 @@ const ScatterChart = React.forwardRef(function ScatterChart( overlayProps, legendProps, axisHighlightProps, - tooltipProps, children, } = useScatterChartProps(props); + + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( @@ -143,7 +140,7 @@ const ScatterChart = React.forwardRef(function ScatterChart( {!props.hideLegend && } - {!props.loading && } + {!props.loading && } {children} @@ -292,17 +289,6 @@ ScatterChart.propTypes = { PropTypes.object, ]), title: PropTypes.string, - /** - * The configuration of the tooltip. - * @see See {@link https://mui.com/x/react-charts/tooltip/ tooltip docs} for more details. - * @default { trigger: 'item' } - */ - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Indicate which axis to display the top of the charts. * Can be a string (the id of the axis) or an object `ChartsXAxisProps`. diff --git a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts index 542b8b3f993e..0399f0543a96 100644 --- a/packages/x-charts/src/ScatterChart/useScatterChartProps.ts +++ b/packages/x-charts/src/ScatterChart/useScatterChartProps.ts @@ -4,7 +4,6 @@ import { ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { ChartsGridProps } from '../ChartsGrid'; import { ChartsLegendProps } from '../ChartsLegend'; import { ChartsOverlayProps } from '../ChartsOverlay'; -import { ChartsTooltipProps } from '../ChartsTooltip'; import type { ChartsVoronoiHandlerProps } from '../ChartsVoronoiHandler'; import { ChartContainerProps } from '../ChartContainer'; import { ZAxisContextProviderProps } from '../context'; @@ -24,7 +23,6 @@ export const useScatterChartProps = (props: ScatterChartProps) => { yAxis, zAxis, series, - tooltip, axisHighlight, voronoiMaxRadius, disableVoronoi, @@ -108,13 +106,6 @@ export const useScatterChartProps = (props: ScatterChartProps) => { ...axisHighlight, }; - const tooltipProps: ChartsTooltipProps = { - trigger: 'item' as const, - ...tooltip, - slots, - slotProps, - }; - return { chartContainerProps, zAxisProps, @@ -125,7 +116,6 @@ export const useScatterChartProps = (props: ScatterChartProps) => { overlayProps, legendProps, axisHighlightProps, - tooltipProps, children, }; }; diff --git a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx index fafe75edf736..b1f035ff1429 100644 --- a/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx +++ b/packages/x-charts/src/SparkLineChart/SparkLineChart.tsx @@ -6,12 +6,7 @@ import { BarPlot } from '../BarChart'; import { LinePlot, AreaPlot, LineHighlightPlot } from '../LineChart'; import { ChartContainer, ChartContainerProps } from '../ChartContainer'; import { DEFAULT_X_AXIS_KEY } from '../constants'; -import { - ChartsTooltip, - ChartsTooltipProps, - ChartsTooltipSlotProps, - ChartsTooltipSlots, -} from '../ChartsTooltip'; +import { ChartsTooltip, ChartsTooltipProps } from '../ChartsTooltip'; import { ChartsAxisHighlight, ChartsAxisHighlightProps } from '../ChartsAxisHighlight'; import { AxisConfig, ChartsXAxisProps, ChartsYAxisProps, ScaleName } from '../models/axis'; import { LineSeriesType, BarSeriesType } from '../models/seriesType'; @@ -27,15 +22,21 @@ export interface SparkLineChartSlots LinePlotSlots, MarkPlotSlots, LineHighlightPlotSlots, - Omit, - ChartsTooltipSlots {} + Omit { + /** + * Custom component for the tooltip popper. + * @default ChartsTooltipRoot + */ + tooltip?: React.ElementType; +} export interface SparkLineChartSlotProps extends AreaPlotSlotProps, LinePlotSlotProps, MarkPlotSlotProps, LineHighlightPlotSlotProps, - BarPlotSlotProps, - ChartsTooltipSlotProps {} + BarPlotSlotProps { + tooltip?: Partial; +} export interface SparkLineChartProps extends Omit { @@ -49,7 +50,6 @@ export interface SparkLineChartProps * Notice it is a single [[AxisConfig]] object, not an array of configuration. */ yAxis?: MakeOptional, 'id'>; - tooltip?: ChartsTooltipProps; axisHighlight?: ChartsAxisHighlightProps; /** * Type of plot used. @@ -142,7 +142,6 @@ const SparkLineChart = React.forwardRef(function SparkLineChart( colors, sx, showTooltip, - tooltip, showHighlight, axisHighlight: inAxisHighlight, children, @@ -164,6 +163,8 @@ const SparkLineChart = React.forwardRef(function SparkLineChart( ...inAxisHighlight, }; + const Tooltip = props.slots?.tooltip ?? ChartsTooltip; + return ( - {showTooltip && } + {showTooltip && } {children} @@ -360,12 +361,6 @@ SparkLineChart.propTypes = { PropTypes.object, ]), title: PropTypes.string, - tooltip: PropTypes.shape({ - classes: PropTypes.object, - slotProps: PropTypes.object, - slots: PropTypes.object, - trigger: PropTypes.oneOf(['axis', 'item', 'none']), - }), /** * Formatter used by the tooltip. * @param {number} value The value to format. diff --git a/packages/x-charts/src/hooks/useAxisEvents.ts b/packages/x-charts/src/hooks/useAxisEvents.ts index c64b730731e3..457028751a5b 100644 --- a/packages/x-charts/src/hooks/useAxisEvents.ts +++ b/packages/x-charts/src/hooks/useAxisEvents.ts @@ -1,12 +1,12 @@ 'use client'; import * as React from 'react'; -import { ChartsContext } from '../context/InteractionProvider'; import { useCartesianContext } from '../context/CartesianProvider'; import { isBandScale } from '../internals/isBandScale'; import { AxisDefaultized } from '../models/axis'; import { getSVGPoint } from '../internals/getSVGPoint'; import { useSvgRef } from './useSvgRef'; import { useDrawingArea } from './useDrawingArea'; +import { useStore } from '../internals/useStore'; function getAsANumber(value: number | Date) { return value instanceof Date ? value.getTime() : value; @@ -16,7 +16,7 @@ export const useAxisEvents = (disableAxisListener: boolean) => { const drawingArea = useDrawingArea(); const { xAxis, yAxis, xAxisIds, yAxisIds } = useCartesianContext(); - const store = React.useContext(ChartsContext)?.store; + const store = useStore(); const usedXAxis = xAxisIds[0]; const usedYAxis = yAxisIds[0]; diff --git a/scripts/x-charts-pro.exports.json b/scripts/x-charts-pro.exports.json index c08727097b80..92608c515908 100644 --- a/scripts/x-charts-pro.exports.json +++ b/scripts/x-charts-pro.exports.json @@ -106,14 +106,10 @@ { "name": "ChartsTooltipClassKey", "kind": "TypeAlias" }, { "name": "ChartsTooltipContainer", "kind": "Function" }, { "name": "ChartsTooltipContainerProps", "kind": "Interface" }, - { "name": "ChartsTooltipContainerSlotProps", "kind": "Interface" }, - { "name": "ChartsTooltipContainerSlots", "kind": "Interface" }, { "name": "ChartsTooltipMark", "kind": "Variable" }, { "name": "ChartsTooltipPaper", "kind": "Variable" }, { "name": "ChartsTooltipProps", "kind": "Interface" }, { "name": "ChartsTooltipRow", "kind": "Variable" }, - { "name": "ChartsTooltipSlotProps", "kind": "Interface" }, - { "name": "ChartsTooltipSlots", "kind": "Interface" }, { "name": "ChartsTooltipTable", "kind": "Variable" }, { "name": "ChartsVoronoiHandler", "kind": "Function" }, { "name": "ChartsVoronoiHandlerProps", "kind": "TypeAlias" }, @@ -266,7 +262,6 @@ { "name": "PiePlotSlots", "kind": "Interface" }, { "name": "PieSeriesType", "kind": "Interface" }, { "name": "PieValueType", "kind": "TypeAlias" }, - { "name": "PopperProps", "kind": "TypeAlias" }, { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "referenceLineClasses", "kind": "Variable" }, { "name": "ScaleName", "kind": "TypeAlias" }, diff --git a/scripts/x-charts.exports.json b/scripts/x-charts.exports.json index 73668e48ed37..f8a96bab5f1d 100644 --- a/scripts/x-charts.exports.json +++ b/scripts/x-charts.exports.json @@ -104,14 +104,10 @@ { "name": "ChartsTooltipClassKey", "kind": "TypeAlias" }, { "name": "ChartsTooltipContainer", "kind": "Function" }, { "name": "ChartsTooltipContainerProps", "kind": "Interface" }, - { "name": "ChartsTooltipContainerSlotProps", "kind": "Interface" }, - { "name": "ChartsTooltipContainerSlots", "kind": "Interface" }, { "name": "ChartsTooltipMark", "kind": "Variable" }, { "name": "ChartsTooltipPaper", "kind": "Variable" }, { "name": "ChartsTooltipProps", "kind": "Interface" }, { "name": "ChartsTooltipRow", "kind": "Variable" }, - { "name": "ChartsTooltipSlotProps", "kind": "Interface" }, - { "name": "ChartsTooltipSlots", "kind": "Interface" }, { "name": "ChartsTooltipTable", "kind": "Variable" }, { "name": "ChartsVoronoiHandler", "kind": "Function" }, { "name": "ChartsVoronoiHandlerProps", "kind": "TypeAlias" }, @@ -254,7 +250,6 @@ { "name": "PiePlotSlots", "kind": "Interface" }, { "name": "PieSeriesType", "kind": "Interface" }, { "name": "PieValueType", "kind": "TypeAlias" }, - { "name": "PopperProps", "kind": "TypeAlias" }, { "name": "PropsFromSlot", "kind": "TypeAlias" }, { "name": "referenceLineClasses", "kind": "Variable" }, { "name": "ScaleName", "kind": "TypeAlias" },