Skip to content

Conversation

@JCQuintas
Copy link
Member

@JCQuintas JCQuintas commented Dec 5, 2025

Split from #20404

Code is the same, but removed the implementation part to decrease complexity.

This should be ready to review/merge as the plugin is not hooked into anything.

Docs on:
https://deploy-preview-20404--material-ui-x.netlify.app/x/react-charts/legend/#toggle-visibility

@JCQuintas JCQuintas self-assigned this Dec 5, 2025
@JCQuintas JCQuintas requested a review from a team as a code owner December 5, 2025 12:05
@JCQuintas JCQuintas added type: new feature Expand the scope of the product to solve a new problem. scope: charts Changes related to the charts. labels Dec 5, 2025
@mui-bot
Copy link

mui-bot commented Dec 5, 2025

Deploy preview: https://deploy-preview-20571--material-ui-x.netlify.app/

Bundle size report

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 🔺+2.69KB(+0.79%) 🔺+776B(+0.76%)
@mui/x-charts-pro 🔺+2.69KB(+0.60%) 🔺+903B(+0.67%)
@mui/x-charts-premium 🔺+1.68KB(+0.38%) 🔺+509B(+0.38%)
@mui/x-date-pickers 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers-pro 0B(0.00%) 0B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)

Details of bundle changes

Generated by 🚫 dangerJS against 7fde6c4

@codspeed-hq
Copy link

codspeed-hq bot commented Dec 5, 2025

CodSpeed Performance Report

Merging #20571 will not alter performance

Comparing JCQuintas:visibility-manager-code (7fde6c4) with master (882da2c)1

Summary

✅ 13 untouched

Footnotes

  1. 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.

Comment on lines +88 to +89
// 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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure about why this is needed. For me D3 takes care of the ordering with stackingOrder

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have to use the exact same order as stackedData.

IIRC the issue was that some ordering functions change the order based on value, so if we have value 0 for a hidden series it would be ordered first/last in the stack.

const keyIndex = keys.indexOf(key);
const seriesId = ids[keyIndex];

if (!isIdentifierVisible?.(`${seriesId}`)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assunme the `${seriesId}` is here to be sure seriesId are string

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, I could move it into the isIdentifierVisible though

}
return d[key] ?? 0;
})
.offset(stackingOffset)(d3Dataset);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would assume the stackingOrder is needed for the visible stack and not for the one with all series.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mentioned above

Comment on lines +106 to +107
// Post-process visibleStackedData to fix positions for hidden series
// Hidden series should collapse to the cumulative position of visible series before them
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm unsure about this part.

On one side, the animations it creates look nice. On the other one, it looks like something that should be the responsability of the animation, not the data processing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hum, I think I can achieve the same by tweaking the animation logic. Let me try

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the necessary changes: 114188a
seems reasonable @bernardobelchior wdyt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its missing line chart adjustments that needs to be made, but it works nicely for barchart, animations are the same

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My only remaining concern would be performances, because we render all the items even the one that ends up being hidden.

But I assume this could be simply solved by something like "if animation is disabled, useBarPlotData filter out hidden series"

Comment on lines +56 to +57
const visibleValues = series.visibleStackedData[dataIndex];
const visibleValueCoordinates = visibleValues.map((v) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit pick: you don't need to rename values by visibleValues in the rendering part since every thing here is based on the visible stuff


export const VISIBILITY_SEPARATOR = '-';

export const buildIdentifier = (ids: string | (string | number)[]) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we be more explicit in types like that?

Suggested change
export const buildIdentifier = (ids: string | (string | number)[]) => {
export const buildIdentifier = (ids: SeriesId | [SeriesId, ItemId]) => {

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, we maybe need to add number as in ids: string | number | (string | number)[], but in general my idea was that this could eventually also be used by things like sankey, which doesn't use seriesId

selectorVisibilityMap,
(visibilityMap) => {
return {
// Return an object as selectors don't correctly memoize direct functions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's the case, then we have an issue with highlight selectors 😮

store,
params,
}) => {
// Manage controlled state
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ther eis an helper for th ewarning messages

useAssertModelConsistencyOutsideOfProduction

Comment on lines +10 to +12
* Function to check if an item is visible based on its identifier.
* @param {string | (string | number)[]} identifier The identifier of the item.
* @returns {boolean} Whether the item is visible.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "identifier" naming is a bit confusing because it conflicts with the identifiers used in highlight and tooltip.

The array signatures looks surprising too.

Just an idea that came in mind while writing the comment:

IsIdentifierVisible = (seriesId: SeriesId, itemId?: string | number) => boolean

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The array makes it easier to use imo, but the types are more complex.

My idea was if it is a string, use as is, but I think a better API might be (id: string|number, ...ids: (string|number)[])

This way we concatenate if there are more than 1 args

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The (id: string|number, ...ids: (string|number)[]) looks effectively better. The array was giving the feeling that we can provide multiple items at the same time

Comment on lines +119 to +120
// Calculate the cumulative sum of all visible series before this one
// Only accumulate values with the same sign
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you're doing back the job done in visibleStackedData. You could "just" need to find the id of the first visible series before this one and use it's stacked value

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scope: charts Changes related to the charts. type: new feature Expand the scope of the product to solve a new problem.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants