[charts] Add Legend actions
Fixes https://github.com/mui/mui-x/issues/19455 Fixes https://github.com/mui/mui-x/issues/12344
Adds action to hide series/item when clicking on their legend.
Works by providing toggleVisibilityOnClick to the chart component's slot props.
slotProps={{
legend: {
toggleVisibilityOnClick: true,
},
}}
Added a new VisibilityManager plugin.
New Public API
hideItem: (identifier: string | (string | number)[]) => void;
showItem: (identifier: string | (string | number)[]) => void;
toggleItem: (identifier: string | (string | number)[]) => void;
Currently available for:
Pie
Scatter
Radar
Line
Bar
Open questions
Should missing charts types also have the behaviour?
- Heatmap: probably not. It doesn't have a default legend, and usually uses the continuous one.
- Sankey: no legend, we might still want to hide/show nodes, which can be done with the
VisibilityManagereventually - Funnel: can be done, not sure it is useful, it felt a bit weird removing a slice, and seemed to have no purpose
Should we animate Scatter and Radar interaction?
Right now both don't have any animation, so I just don't render the component. If we want animations we will need to handle those.
Deploy preview: https://deploy-preview-20404--material-ui-x.netlify.app/
Updated pages:
Bundle size report
Bundle size will be reported once CircleCI build #704162 finishes.
Generated by :no_entry_sign: dangerJS against b06a1800e7706b1e899671e91594294e8bb50417
CodSpeed Performance Report
Merging #20404 will not alter performance
Comparing JCQuintas:legend-actions (e200382) with master (882da2c)[^unexpected-base]
[^unexpected-base]: No successful run was found on master (5405d77) during the generation of this report, so 882da2c was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.
Summary
✅ 13 untouched
Should missing charts types also have the behaviour?
I don't think so. Looks weird for now. Lets wait to see if there are real usecases
Should we animate Scatter and Radar interaction?
Doe sit impact a lot the technical solution? I don't think users will ask for it, so for now not having them looks ok
Should we animate Scatter and Radar interaction?
Doe sit impact a lot the technical solution? I don't think users will ask for it, so for now not having them looks ok
It is a different approach, but it is not hard. It is just that right now they don't have any transition animation, so I wasn't sure it would make sense to add animations for these specific interactions.
Maybe we keep it out for now and take a further look once we divide charts up in composable parts in the future
This pull request has conflicts, please resolve those before we can evaluate the pull request.
From the gifs, I can see that we are not changing the axis range based on hiding/viewing a series.
We can keep it out of scope, until users request for it. Later on, a setting like Zoom filtermode: discard/keep, could be helpful for some use cases.
From the gifs, I can see that we are not changing the axis range based on hiding/viewing a series.
We can keep it out of scope, until users request for it. Later on, a setting like Zoom filtermode: discard/keep, could be helpful for some use cases.
Yeah, I intend to add it as a future iteration. Will create an issue so we don't forget 😆
This pull request has conflicts, please resolve those before we can evaluate the pull request.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
One solutoin for your staking issues
index c6c0b2e03e..c5b04c7c72 100644
--- a/packages/x-charts/src/BarChart/seriesConfig/bar/seriesProcessor.ts
+++ b/packages/x-charts/src/BarChart/seriesConfig/bar/seriesProcessor.ts
@@ -86,7 +86,12 @@ const seriesProcessor: SeriesProcessor<'bar'> = (params, dataset, isIdentifierVi
.offset(stackingOffset)(d3Dataset);
// We sort the keys based on the original stacking order to ensure consistency
- const idOrder = stackedData.sort((a, b) => a.index - b.index).map((s) => s.key);
+ const idOrder = stackedData.map((s) => s.key);
+
+ const idToIndexMap: { [key: string]: number } = {};
+ idOrder.forEach((id, index) => {
+ idToIndexMap[id] = index;
+ });
// Compute visible stacked data
const visibleStackedData = d3Stack<any, DatasetElementType<number | null>, SeriesId>()
@@ -120,8 +125,8 @@ const seriesProcessor: SeriesProcessor<'bar'> = (params, dataset, isIdentifierVi
...series[id],
data,
hidden,
- stackedData: stackedData[index] as [number, number][],
- visibleStackedData: visibleStackedData[index] as [number, number][],
+ stackedData: stackedData[idToIndexMap[id]] as [number, number][],
+ visibleStackedData: visibleStackedData[idToIndexMap[id]] as [number, number][],
};
});
});
About the diverging I looked at the D3 implementation
function d3StackOffsetDiverging(series, order) {
if (!((n = series.length) > 0)) return;
for (var i, j = 0, d, dy, yp, yn, n, m = series[order[0]].length; j < m; ++j) {
for (yp = yn = 0, i = 0; i < n; ++i) {
if ((dy = (d = series[order[i]][j])[1] - d[0]) > 0) {
d[0] = yp, d[1] = yp += dy;
} else if (dy < 0) {
d[1] = yn, d[0] = yn += dy;
} else {
// Here I would like to make a distinction between if the series has a negative or positive value when visible
// Such that if negative, we do d[0] = yn, d[1] = yn;
// if positive, we do d[0] = yp, d[1] = yp;
d[0] = 0, d[1] = dy;
}
}
}
}
One solutoin for your staking issues
Which solution is this trying to fix? 🤔 I put it in but put couldn't figure the difference
The version I tried was before you pushed your fix https://github.com/mui/mui-x/pull/20404/commits/9cc928a0ee676e5ff21c442acf6f78ccd9c59c8f