Skip to content

Commit 68cc9b0

Browse files
committed
[charts] Allow skipping tooltip render
1 parent 95f7c7d commit 68cc9b0

3 files changed

Lines changed: 16 additions & 65 deletions

File tree

docs/data/charts/tooltip/tooltip.md

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ You can replace the default tooltip in single component charts by using slots.
134134
<LineChart slots={{ tooltip: CustomItemTooltip }} />
135135
```
136136

137-
With compositon, you can use your component inside the container.
137+
With composition, you can use your component inside the container.
138138

139139
```jsx
140140
<ChartContainer>
@@ -201,25 +201,6 @@ The following demo shows how to use additional hooks such as `useXAxis()` and `u
201201
To keep the default placement, use the `<ChartsTooltipContainer />` wrapper.
202202
It accepts a prop `trigger = 'item' | 'axis'` that defines when the Popper should open.
203203

204-
:::warning
205-
The tooltip might not open if the ChartsTooltipContainer isn't rendered.
206-
207-
For example the following code does not work.
208-
209-
```jsx
210-
if (tooltipData === null) {
211-
return null;
212-
}
213-
214-
return (
215-
<ChartsTooltipContainer trigger="item">
216-
{/** My content **/}
217-
</ChartsTooltipContainer>
218-
);
219-
```
220-
221-
:::
222-
223204
##### Item content
224205

225206
The `useItemTooltip()` hook provides the information about the current item the user is interacting with.

packages/x-charts/src/ChartsTooltip/ChartsTooltipContainer.tsx

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { styled, useThemeProps } from '@mui/material/styles';
77
import Popper, { PopperProps } from '@mui/material/Popper';
88
import NoSsr from '@mui/material/NoSsr';
99
import { useSvgRef } from '../hooks/useSvgRef';
10-
import { TriggerOptions, usePointerType } from './utils';
10+
import { TriggerOptions, useIsDesktop } from './utils';
1111
import { ChartsTooltipClasses } from './chartsTooltipClasses';
1212
import { useSelector } from '../internals/store/useSelector';
1313
import { useStore } from '../internals/store/useStore';
@@ -62,7 +62,7 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) {
6262
const { trigger = 'axis', classes, children, ...other } = props;
6363

6464
const svgRef = useSvgRef();
65-
const pointerType = usePointerType();
65+
const isDesktop = useIsDesktop();
6666

6767
const popperRef: PopperProps['popperRef'] = React.useRef(null);
6868
const positionRef = useLazyRef(() => ({ x: 0, y: 0 }));
@@ -79,8 +79,6 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) {
7979
: selectorChartsInteractionItemIsDefined,
8080
);
8181

82-
const popperOpen = pointerType !== null && isOpen; // tooltipHasData;
83-
8482
React.useEffect(() => {
8583
const element = svgRef.current;
8684
if (element === null) {
@@ -123,15 +121,15 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) {
123121
name: 'offset',
124122
options: {
125123
offset: () => {
126-
if (pointerType?.pointerType !== 'touch') {
124+
if (isDesktop) {
127125
// The popper offset: [skidding, distance]
128126
return [0, 8];
129127
}
130128
return [0, 64];
131129
},
132130
},
133131
},
134-
...(pointerType?.pointerType === 'mouse'
132+
...(isDesktop
135133
? [] // Keep default behavior
136134
: [
137135
{
@@ -142,7 +140,7 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) {
142140
},
143141
]),
144142
],
145-
[pointerType],
143+
[isDesktop],
146144
);
147145

148146
if (trigger === 'none') {
@@ -151,11 +149,11 @@ function ChartsTooltipContainer(inProps: ChartsTooltipContainerProps) {
151149

152150
return (
153151
<NoSsr>
154-
{popperOpen && (
152+
{isOpen && (
155153
<ChartsTooltipRoot
156154
className={classes?.root}
157-
open={popperOpen}
158-
placement={pointerType?.pointerType === 'mouse' ? 'right-start' : 'top'}
155+
open={isOpen}
156+
placement={isDesktop ? 'right-start' : 'top'}
159157
popperRef={popperRef}
160158
anchorEl={anchorEl}
161159
modifiers={modifiers}

packages/x-charts/src/ChartsTooltip/utils.tsx

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
'use client';
22
import * as React from 'react';
3+
import useMediaQuery from '@mui/material/useMediaQuery';
34
import { useSvgRef } from '../hooks';
45

56
type MousePosition = {
@@ -9,6 +10,9 @@ type MousePosition = {
910
height: number;
1011
};
1112

13+
// Taken from @mui/x-date-time-pickers
14+
const desktopModeMediaQuery = '@media (pointer: fine)';
15+
1216
export type UseMouseTrackerReturnValue = null | MousePosition;
1317

1418
/**
@@ -57,42 +61,10 @@ export function useMouseTracker(): UseMouseTrackerReturnValue {
5761
return mousePosition;
5862
}
5963

60-
type PointerType = Pick<MousePosition, 'pointerType'>;
61-
62-
export function usePointerType(): null | PointerType {
63-
const svgRef = useSvgRef();
64-
65-
// Use a ref to avoid rerendering on every mousemove event.
66-
const [pointerType, setPointerType] = React.useState<null | PointerType>(null);
67-
68-
React.useEffect(() => {
69-
const element = svgRef.current;
70-
if (element === null) {
71-
return () => {};
72-
}
73-
74-
const handleOut = (event: PointerEvent) => {
75-
if (event.pointerType !== 'mouse') {
76-
setPointerType(null);
77-
}
78-
};
79-
80-
const handleEnter = (event: PointerEvent) => {
81-
setPointerType({
82-
pointerType: event.pointerType as PointerType['pointerType'],
83-
});
84-
};
85-
86-
element.addEventListener('pointerenter', handleEnter);
87-
element.addEventListener('pointerup', handleOut);
88-
89-
return () => {
90-
element.removeEventListener('pointerenter', handleEnter);
91-
element.removeEventListener('pointerup', handleOut);
92-
};
93-
}, [svgRef]);
64+
export function useIsDesktop(): boolean {
65+
const isDesktop = useMediaQuery(desktopModeMediaQuery, { defaultMatches: true });
9466

95-
return pointerType;
67+
return isDesktop;
9668
}
9769

9870
export type TriggerOptions = 'item' | 'axis' | 'none';

0 commit comments

Comments
 (0)