-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[charts] Fix legend position affecting toolbar's position #19257
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
Conversation
Deploy preview: https://deploy-preview-19257--material-ui-x.netlify.app/ Bundle size report
|
CodSpeed Performance ReportMerging #19257 will not alter performanceComparing Summary
Footnotes |
[`&:has(.${chartsToolbarClasses.root})`]: { | ||
position: 'relative', | ||
paddingTop: '56px', | ||
}, | ||
[`& > .${chartsToolbarClasses.root}`]: { | ||
position: 'absolute', | ||
top: 0, | ||
left: '50%', | ||
transform: 'translateX(-50%)', | ||
zIndex: 1, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would rather not use absolute positioning to fix this.
Maybe we can make use of the grid
css prop to position things in the correct places, like using grid-template-areas
/* Regular */
grid-template-areas:
"toolbar"
"legend"
"chart";
/* Left */
grid-template-areas:
"toolbar toolbar"
"chart legend";
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it, I'll explore this direction
66a7c19
to
84063ba
Compare
Bundle size report
|
ca3e2cd
to
d315069
Compare
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
d315069
to
6a25548
Compare
return `"toolbar toolbar" | ||
"chart chart"`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would this work?
return `"toolbar toolbar" | |
"chart chart"`; | |
return `"toolbar" | |
"chart"`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
direction?: Direction, | ||
position?: Position, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make these mandatory? Same applies to the other functions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
const getTemplateRows = (hideLegend: boolean, direction?: Direction) => { | ||
if (direction === 'vertical') { | ||
if (hideLegend) { | ||
return '1fr'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't 'auto' work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
87c31d4
to
c0088f2
Compare
if (position?.horizontal === 'end') { | ||
return 'flex-end'; | ||
} | ||
return `${width ? 'auto' : '1fr'} auto`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Had to handle a tricky migration issue here. When moving from flexbox to grid, we lost the automatic width handling that flexbox gives us for free.
With flexbox, child elements would automatically size correctly whether they had an explicit width (like width: 200px) or needed to expand (width: 100%). Grid doesn't do this - you have to tell it upfront how to size the columns.
My fix was to make the grid columns conditional based on whether the component has a width prop. If there's a width, use auto
so it respects the explicit sizing. If no width, use 1fr
so the element can expand to fill the space.
This way we keep the same flexible behavior we had with flexbox.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we use minmax(auto, 1fr) auto
in this case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this, but it’s not working. The layout keeps defaulting to 1fr whenever there’s extra space available. For example, in this demo (https://deploy-preview-19257--material-ui-x.netlify.app/x/react-charts/pie/#basics
), the chart container width defaults to 1fr, but the chart itself stays fixed at 200px.

Thanks, @sai6855, for your contribution! This PR seems to fix the bug from what I've tested. I'm wondering if we should consider a longer term solution. We can't do breaking changes at the moment, but I'd like to reflect on what a good API for laying a chart's elements out are. Currently, I'm entertaining the idea of using Developers who want to customize the position of any of these elements can use CSS to apply a more specific gridTemplate: "toolbar ."
"chart legend"; We could then remove the position slot props for legends because they wouldn't be necessary. @JCQuintas @alexfauquette what do you think of this long-term proposal? If it makes sense, we could consider reshaping this PR to start moving towards that vision while keeping backwards compatibility where possible. |
I feel that is too hidden away tbh. It would work nicely with base-ui probably eventually, but as a component we probably want to have props for that instead. |
Do you have any suggestion on how that would be implemented? If we want to position the toolbar the same way the legend is positioned, how do we disambiguate when both have |
What do you mean by "disambiguate"? The toolbar would be on its own, so we would have to add a row to the top or bottom of the current rows. The toolbar can take the full width and if it needs to be aligned to a side it can align itself. As far as I understand the toolbar does't have a vertical layout, so it should be simpler, as |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems to be working nicely. Added a suggestion to get rid of getGridTemplateAreasWithToolBar
), | ||
}, | ||
[`&:not(:has(.${chartsToolbarClasses.root}))`]: { | ||
gridTemplateAreas: getGridTemplateAreasWithoutToolBar( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gridTemplateAreas: getGridTemplateAreasWithoutToolBar( | |
gridTemplateAreas: getGridTemplateAreas( |
gridTemplateAreas: getGridTemplateAreasWithToolBar( | ||
ownerState.hideLegend, | ||
ownerState.legendDirection, | ||
ownerState.legendPosition, | ||
), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
gridTemplateAreas: getGridTemplateAreasWithToolBar( | |
ownerState.hideLegend, | |
ownerState.legendDirection, | |
ownerState.legendPosition, | |
), | |
gridTemplateAreas: addToolbar(getGridTemplateAreas( | |
ownerState.hideLegend, | |
ownerState.legendDirection, | |
ownerState.legendPosition, | |
)), |
return 'center'; | ||
}; | ||
|
||
const getGridTemplateAreasWithToolBar = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const getGridTemplateAreasWithToolBar = ( | |
const addToolbar = (template: string) => { | |
const length = template.split('\n').at(0).split(' ').length | |
let toolbar = 'toolbar' | |
for (let i = 1; i < length; i+=1) { | |
toolbar += ' toolbar' | |
} | |
return `${toolbar} | |
${template}` | |
} |
}; | ||
|
||
const getAlign = (direction?: Direction, position?: Position) => { | ||
const getGridTemplateAreasWithoutToolBar = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const getGridTemplateAreasWithoutToolBar = ( | |
const getGridTemplateAreas = ( |
If the legend and the toolbar have the equal
Yeah, it doesn't at the moment, but the problem is still valid if we can only position the toolbar on top and bottom. My concern is that the current API isn't enough to fully customize the positioning of both the toolbar and the legend. This PR fixes the bug it references, but I think the API can still be improved. |
e2f92c1
to
82a06c3
Compare
@JCQuintas Removed both
|
closes #19189
Working preview:
https://stackblitz.com/edit/dbfc2gr7?file=src%2FDemo.tsx