-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[charts] Add configurable slots to toolbar #17712
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] Add configurable slots to toolbar #17712
Conversation
|
Deploy preview: https://deploy-preview-17712--material-ui-x.netlify.app/ Bundle size reportTotal Size Change: @mui/x-charts-pro/ChartContainerPro parsed: Show 7 more bundle changes@mui/x-charts/RadarChart parsed: |
CodSpeed Performance ReportMerging #17712 will not alter performanceComparing Summary
|
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
30611b5 to
a80b544
Compare
| /** | ||
| * Slots to customize charts' components. | ||
| */ | ||
| slots?: Partial<ChartsSlots>; | ||
| /** | ||
| * The props for the slots. | ||
| */ | ||
| slotProps?: Partial<ChartsSlotProps>; | ||
| }; |
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.
This is a break away from the current pattern of only providing slots to the higher-level chart components (e.g., LineChart) or providing slots directly to the components that render them (e.g., ChartsXAxis).
I'd like your opinion on this.
The reason I chose this option is because it allows defining the base slots (e.g., icons, buttons, tooltips) for the whole chart. This means that all toolbar components (and potentially others in the future) will use these components.
This contrasts with the current approach, which would be to pass the slots directly to the toolbar and, if using composition, to its descendants as well.
My reasoning was: if we're going to override the components using slots, might as well do it for all components in a chart. If we want to override one by one, we can use composition and the render prop if needed.
If we kept the current approach, overriding the slots when using composition would be cumbersome because we would need to set the slots in all components:
function CustomToolbar() {
return <Toolbar>
<ChartToolbarZoomInButton slots={{ baseIconButton: CustomButton }} />
<ChartToolbarZoomOutButton slots={{ baseIconButton: CustomButton }} />
</Toolbar>
}With the approach taken in this PR, there's a single place to define the slots for base components, such as icons, buttons and tooltips.
I understand this will create two ways of using slots:
- The current one for all components;
- The new one for the toolbar.
And that's where I'd like to hear your opinion. Do you think it's better to strive for consistency in exchange for convenience? What are your thoughts?
For context, here's a PR that implements this pattern and the render prop, along with a demo to see how it looks like.
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'll have to sleep on the idea 😆
It seems an interesting approach, but it might be annoying to have both at the same time, as you mentioned 🤔
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.
@JCQuintas have you slept on the idea? What did you dream about? 😛
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 like the idea of moving it to a single place, but I'm not sure it would be the best moment to do so.
I think the current idea is to still, eventually, provide a more base-ui like offering for charts, this would mean that the slots go away in favour of composition, at least in that version.
I'm not sure if having a global context for slots would make this easier or harder tbh 🤔
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.
Yeah, I don't like the idea of having a different pattern either.
I think the current idea is to still, eventually, provide a more base-ui like offering for charts, this would mean that the slots go away in favour of composition, at least in that version.
How so? The idea of this approach is to be similar to the Data Grid approach, which is supposed to be design system agnostic.
So, concluding, you think it's better to keep the current pattern instead of introducing a new one, is that it?
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 like to hear what @alexfauquette has to say, as he might be more informed on this
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 don't see issues with having both strategies since they solve two distinct use-cases:
- Direct slot propagation for big component: You want to replace the tooltip, legend, overlay. We can make it easy since their is only one of them in the chart.
- You want to replace a MUI component: They can be multiple so the root props are propagated thanks to a context to be transparent.
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.
This was further discussed in this PR.
alexfauquette
left a comment
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'm good with the idea
| /** | ||
| * Slots to customize charts' components. | ||
| */ | ||
| slots?: Partial<ChartsSlots>; | ||
| /** | ||
| * The props for the slots. | ||
| */ | ||
| slotProps?: Partial<ChartsSlotProps>; | ||
| }; |
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 don't see issues with having both strategies since they solve two distinct use-cases:
- Direct slot propagation for big component: You want to replace the tooltip, legend, overlay. We can make it easy since their is only one of them in the chart.
- You want to replace a MUI component: They can be multiple so the root props are propagated thanks to a context to be transparent.
|
|
||
| /** | ||
| * Get the slots and slotProps from the nearest `ChartDataProvider` or `ChartDataProviderPro`. | ||
| * @returns {ChartsSlotsContextValue} The slots and slotProps from the context. | ||
| */ | ||
| export function useChartToolbarSlots< |
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.
Not sure it should be associated with the Toolbar.
This could be extended to all MUI components such that we can also remove the Paper, Popper, Typography.
Not sure also it should be exported, because I don't see a usage we could encourage.
The slots are here to let user the ability to override our default components.
For example slots={{ iconButton: MyCompanyButton }}
If they are at the level of creating their own component, they will either:
- Reuse our component, but then it's transparent
<ChartsDownloadButton />The rendered button already come from the context - Reuse our component with render
<ChartsDownloadButton render={() => <MyCompanyButton .../>}/> - Do their own stuff
MyToolbarButton = () => Button<MyCompanyButton .../>
The only use cases if they want to have built-in way to switch from one set of components to another
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.
Not sure it should be associated with the Toolbar.
Yeah, I had that doubt as well. We'll probably want to use this for more things, so I think it's better to be generic.
This could be extended to all MUI components such that we can also remove the
Paper,Popper,Typography.
Good point 👍 we'll probably want to do that.
Not sure also it should be exported, because I don't see a usage we could encourage.
If we're able to set them in the ChartsDataProvider, I agree there's no point in exporting the ChartsSlotsContext. Otherwise, I think we'll need to export it so that users can replace Material components with their own when using composition.
6187353 to
298bf52
Compare
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
3a69d4f to
2df9493
Compare
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
2df9493 to
c25776e
Compare
alexfauquette
left a comment
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.
Looks nice, I'm impatient to see how this DX will evolve 👍
It might need some extra love in the documentation to avoid confusion
| ChartsAxisSlots, | ||
| ChartsToolbarSlots, | ||
| Partial<ChartsSlots> {} |
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.
Is it to anticipate the addition of chart export for the Funnel in an upcoming PR?
Because here you add slots that have no effect on the 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.
Which slots have no effect on the funnel?
These are the toolbar's slots, can't all charts accept a toolbar, in theory?
Thanks! Yeah, I think it'll be nice!
Yeah, I'm adding some more docs in this PR. Do you think there's still some parts that should be better documented? |
Part of #17557.
Add toolbar slots to all charts that render a toolbar.
This PR introduces a different way to define slots, which I'm not sure about. I'd like to hear your thoughts in this comment.
This follow-up PR contains an example on how to use the different methods: slots and render props.