Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Charts - Tooltip - custom item content #10352

Closed
2 tasks done
wascou opened this issue Sep 15, 2023 · 12 comments · Fixed by #12408
Closed
2 tasks done

Charts - Tooltip - custom item content #10352

wascou opened this issue Sep 15, 2023 · 12 comments · Fixed by #12408
Labels
component: charts This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation support: question Community support but can be turned into an improvement

Comments

@wascou
Copy link
Contributor

wascou commented Sep 15, 2023

Duplicates

  • I have searched the existing issues

Latest version

  • I have tested the latest version

Summary 💡

I would like to have documentation to know how to implement this.

Examples 🌈

There's no documentation at the moment or example in all the example pieces of code.
Tooltip page is not mentionning it:https://mui.com/x/react-charts/tooltip/
It's specified in https://mui.com/x/api/charts/charts-tooltip/ as "itemContent".
I've also tried to figure out how it works by coding an example.

<ScatterChart
     ...
      tooltip={{
        itemContent: (params: any) => {
          console.log(params)

          return null
        }
      }}
    />

Motivation 🔦

I would like to enrich the chart experience with a correct UI.

Order ID 💳 (optional)

No response

@wascou wascou added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Sep 15, 2023
@oliviertassinari oliviertassinari added the component: charts This is the name of the generic UI component, not the React module! label Sep 16, 2023
@alexfauquette
Copy link
Member

In brief, to unlock you:

itemContent is passed here

And it expects a component that get following props: itemData={itemData} series={series} sx={sx} classes={classes}

itemData is an object that identify which item triggers the tooltip (type os the series, its id and if needed the index of the element in the series)
series is the defaultized config of the triggered series

Not sure it's a "correct UI", but this codesandbox should help to understand how to use it

https://codesandbox.io/s/determined-dew-mkctjw?file=/Demo.tsx

@alexfauquette alexfauquette added support: question Community support but can be turned into an improvement and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Sep 25, 2023
@wascou
Copy link
Contributor Author

wascou commented Sep 30, 2023

Hey @alexfauquette

Thanks for this. I succeeded to use the itemContent component in my ScatterChart.

However, in my serie, I have object with a lot of attributes and in the CustomItemTooltipContent function passed to the trigger.ItemContent param, I can only have access to x, y and id parameters (ScatterValueType), not the all object attributes.

Do you know I can work around that?

@alexfauquette
Copy link
Member

Sorry for the delay, I just saw I did not answer your last question.

The tooltip item content gets itemData and series. From that you can retrieve the entire object defining the scatter point

Here is an example with additional information

image

https://codesandbox.io/s/vibrant-violet-nj83jr?file=/Demo.tsx

const CustomItemTooltipContent = (props) => {
  const { itemData, series } = props;
  return (
    <Paper sx={{ padding: 3, backgroundColor: series.color }}>
      <p>{series.label}</p>
      <p>x: {series.data[itemData.dataIndex].x.toFixed(2)}</p>
      <p>y: {series.data[itemData.dataIndex].y.toFixed(2)}</p>
      <p>
        additional value: {series.data[itemData.dataIndex].other.toFixed(2)}
      </p>
      <p>
        other additional value:{" "}
        {series.data[itemData.dataIndex].other2.toFixed(2)}
      </p>
    </Paper>
  );
};

@wascou
Copy link
Contributor Author

wascou commented Nov 4, 2023

Thanks, working as espected. Two things on a side note:

  1. if used with ChartsTooltip, there's a deprecation on itemContent which moved to the slots prop.
  2. CustomItemToolTipContent is shown when the mouseover event is triggered (logic behavior)

@alexfauquette
Copy link
Member

if used with ChartsTooltip, there's a deprecation on itemContent which moved to the slots prop.

Yes, I moved it to slots for coherence with the rest of the libraries

CustomItemToolTipContent is shown when the mouseover event is triggered (logic behavior)

You mean that you're manually triggering the mouseover event on scatter chart items?

@wascou
Copy link
Contributor Author

wascou commented Nov 5, 2023

I mean The tooltip code is triggered only if you put your mouse over the data point in the chart. If you have some rendering conditions in this part, it's run only on mouse over.

@alexfauquette alexfauquette added the docs Improvements or additions to the documentation label Mar 8, 2024
Copy link

⚠️ This issue has been closed.
If you have a similar problem, please open a new issue and provide details about your specific problem.
If you can provide additional information related to this topic that could help future readers, please feel free to leave a comment.

How did we do @wascou?
Your experience with our support team matters to us. If you have a moment, please share your thoughts through our brief survey.

@jwitthaus
Copy link

jwitthaus commented Jun 5, 2024

in either way (as tooltip and slot) I'm getting this error when using axisContent. It is only working for itemContent
Cannot read properties of undefined (reading 'dataIndex')
TypeError: Cannot read properties of undefined (reading 'dataIndex')
at CustomItemTooltipContent (http://localhost:3000/tierpension/main.c140242e13170ec32343.hot-update.js:55:46)
at renderWithHooks (http://localhost:3000/tierpension/static/js/bundle.js:105545:22)
at mountIndeterminateComponent (http://localhost:3000/tierpension/static/js/bundle.js:109516:17)
at beginWork (http://localhost:3000/tierpension/static/js/bundle.js:110819:20)
at HTMLUnknownElement.callCallback (http://localhost:3000/tierpension/static/js/bundle.js:95801:18)
at Object.invokeGuardedCallbackDev (http://localhost:3000/tierpension/static/js/bundle.js:95845:20)
at invokeGuardedCallback (http://localhost:3000/tierpension/static/js/bundle.js:95902:35)
at beginWork$1 (http://localhost:3000/tierpension/static/js/bundle.js:115800:11)
at performUnitOfWork (http://localhost:3000/tierpension/static/js/bundle.js:115048:16)
at workLoopSync (http://localhost:3000/tierpension/static/js/bundle.js:114971:9)

@XpTo2k
Copy link

XpTo2k commented Jul 24, 2024

@alexfauquette hi there!
I trying to do this on a line chart but I'm having a problem reaching itemData.dataIndex

In the bar chart this value is available but not in line chart.

@alexfauquette
Copy link
Member

Because the notion of item tooltip for the line chart is not well defined. I would not recommend using item tooltip for line chart

You could get a more advance customization example in #13944

If it does not solve your issue, please consider opening another one in which you explain what you try to achieve.

@ThreeCrown
Copy link

I am currently trying to manipulate the Tooltip for a BarChart. The problem seems to be that When I hover over both x axis groups, it displays all the data in the series instead of just the items I am wanting to display that are relevant to group. I was wanting to attempt to keep it as one chart rather than breaking it up into two charts.

    <BarChart
      dataset={data}
      xAxis={[{ scaleType: 'band', dataKey: 'group' }]}
      series={[
        { dataKey: 'unread', stack: 'unread', label: 'Unread' },
        { dataKey: 'confirmed', stack: 'confirmed', label: 'Confirmed' },
        { dataKey: 'completedOpen', stack: 'completed', label: 'Completed' },
        { dataKey: 'ignored', stack: 'ignored', label: 'Ignored' },
        { dataKey: 'total', stack: 'completedConfirmed', label: 'Total' },
        { dataKey: 'completed', stack: 'completedConfirmed', label: 'Completed' },
        { dataKey: 'assigned', stack: 'assigned', label: 'Assigned' },
        { dataKey: 'unassigned', stack: 'assigned', label: 'Unassigned' },
      ]}
      width={600}
      height={300}
      slotProps={{
        legend: { hidden: true },
      }}
      tooltip={{
        itemContent: CustomTooltipContent,
        trigger: 'axis',
      }}
    />
    ```
    Data being passed:
    ```
      const data = [
    {
      group: 'Open Bugs',
      unread: bugReportStatus.unread,
      confirmed: bugReportStatus.confirmed,
      ignored: bugReportStatus.ignored,
      completedOpen: bugReportStatus.completed,
      totalOpen:
        bugReportStatus.unread +
        bugReportStatus.confirmed +
        bugReportStatus.ignored +
        bugReportStatus.completed,
    },
    {
      group: 'Current Confirmed',
      total: bugReportStatus.confirmed,
      completed: bugReportStatus.completed,
      assigned:
        bugReportStatus.crownAssigned +
        bugReportStatus.snowAssigned +
        bugReportStatus.retroAssigned,
      unassigned:
        bugReportStatus.confirmed +
        bugReportStatus.completed -
        (bugReportStatus.crownAssigned +
          bugReportStatus.snowAssigned +
          bugReportStatus.retroAssigned),
    },
  ];

And I tried passing in a custom Tooltip:

const CustomTooltipContent: React.FC = (props) => {
 const { itemData, series } = props;
 const relevantDataKeys: Record<string, string[]> = {
   'Open Bugs': ['unread', 'confirmed', 'ignored', 'completedOpen'],
   'Current Confirmed': ['total', 'completed', 'assigned', 'unassigned'],
 };
 const hoveredGroup = itemData.value;
 const keys = relevantDataKeys[hoveredGroup] || [];

 return (
   <Paper sx={{ p: '1em' }}>
     <p>Group: {hoveredGroup}</p>
     {keys.map((key, idx) => {
       const seriesItem = series.find((s) => s.label === key);
       if (seriesItem) {
         return (
           <p key={idx}>
             {key}: {seriesItem.data[itemData.dataIndex]}
           </p>
         );
       }
       return null;
     })}
   </Paper>
 );
};

@alexfauquette
Copy link
Member

@ThreeCrown This issue is closed since a long time. Could you please open a new one with a codesandbox reproduction such that we can experiment with your issue.

This one should be a good starting point: https://codesandbox.io/p/sandbox/wqd5xt?file=%2Fsrc%2FDemo.tsx%3A6%2C14

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: charts This is the name of the generic UI component, not the React module! docs Improvements or additions to the documentation support: question Community support but can be turned into an improvement
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants