Open siriwatknp opened 2 years ago
So, if I understand this correctly, you're proposing that the components.x
is a shorter way of writing slotProps.x.component
, yes?
So, if I understand this correctly, you're proposing that the
components.x
is a shorter way of writingslotProps.x.component
, yes?
hmm, I forgot that we can use component
inside slotsProps
:
<Select
slotProps={{
listbox: {
component: 'div',
}
}}
/>
This sounds better than having another components
prop.
Generally, I see two changes are proposed here:
component
prop, so that it is used to customize the leaf element (similarly to the as
prop).components
prop that would act as a shortcut to slotProps.x.component
.Do I understand the intent correctly?
Assuming so, this proposal would only make sense in styled libraries (Material UI and Joy UI). In MUI Base, as explained in https://github.com/mui/material-ui/issues/34333#issuecomment-1251007834, the component
is almost exclusively a DOM node, so it does not have the as
prop.
That being said, if we decide to go with option 1 I listed above, the component
prop would be unnecessary in MUI Base (as was already proposed in https://github.com/mui/material-ui/issues/28189). We could leave it as is (as an alias for slots.root
), but it would have a different meaning in styled vs unstyled libraries.
Just clarifying that I understand the proposal correctly. We would have slots
and slotsProps
in Mui Base, Material UI and Joy UI, that would behave the same (replace completely the slot that is being rendered). For e.g.:
const Root = slots.root ?? DefaultRootComponent;
Apart from this, in the components inside Material UI and Joy UI, there would be a component
prop which is basically an alias for the as
prop in emotion (so that when it is used, all styles that were previously defined will still be applied). As all slots would be compossible components, we should already have the support for the component
prop there, so we should need only one component prop per component.
We don't really need this in Mui Base, as the behavior is the same as slots.root
as we don't have any styles, but that is a different discussion, already linked in https://github.com/mui/material-ui/issues/34334#issuecomment-1251043750.
Btw, this is how it already works in Material UI, so I don't expect big change anyway, unless I am misunderstanding the proposal.
so we should need only one component prop per component.
Yes, the component
prop can be considered as a shortcut for slotsProps.component
. If both are provided, slotsProps.component
should have higher priority. cc @michaldudak
Btw, this is how it already works in Material UI, so I don't expect big change anyway, unless I am misunderstanding the proposal.
I'd say that I expect big change for Material UI because most components are using another pattern. e.g. Accordion has TransitionComponent
and TransitionProps
. This will be breaking changes:
// current
<Accordion TransitionComponent={Slide} TransitionProps={{ delay: 100 }} />
// new
<Accordion slots={{ transition: Slide }} slotsProps={{ transition: { delay: 100 } }} />
Marked this as RFC for Material UI and Joy UI only.
I'd say that I expect big change for Material UI because most components are using another pattern. e.g. Accordion has TransitionComponent and TransitionProps. This will be breaking changes:
// current <Accordion TransitionComponent={Slide} TransitionProps={{ delay: 100 }} /> // new <Accordion slots={{ transition: Slide }} slotsProps={{ transition: { delay: 100 } }} />
What I meant is that in terms of behavior it will behave the same. For the props surface, we could support both for smoother migration and provide codemods if people want to migrate to the new paradigm sooner.
What I meant is that in terms of behavior it will behave the same.
Not necessarily. The current pattern in Material UI uses the as
prop to modify the leaf component:
const AutocompletePaper = styled(Paper, { /* ... */ });
/* ... */
<AutocompletePaper
ownerState={ownerState}
as={PaperComponent}
{...componentsProps.paper}
className={clsx(classes.paper, componentsProps.paper?.className)}
>
whereas the slots
prop would replace the whole slot (unless it has a different behavior in styled vs unstyled libraries).
For the props surface, we could support both for smoother migration and provide codemods if people want to migrate to the new paradigm sooner
Yep, agree. We can start introducing slots
and slotsProps
in v5 with a codemod and then deprecate the existing props, e.g. TransitionComponent.
whereas the slots prop would replace the whole slot (unless it has a different behavior in styled vs unstyled libraries).
Yep, component props is "as" and the slot props behave the same as the component props we have on some components, for example TransitionComponent
, PopperComponent
etc.
Update: Joy UI already follows this approach.
This issue can be closed once all Material UI components support slots
and slotProps
. cc @DiegoAndai
Hi there,
I've been trying to understand the possibilities of the slots
and slotProps
with help of:
But I'm not sure its capable of what I'm trying to do.. maybe someone could give some advice?
I have a React Component thats based on the MUI Base Input
-> which is InputCalculate
(Math operations inside of Input field)
Now with the NumberInput
that has been released I've been trying to use the slots
prop to render my InputCalculate
instead of the default.
Can anyone advise me how I can render a complete different HTML structure / Component and also give it props? The docs I've read are giving me the impression I can only change the HTML Tag (ol to ul, button to a etc.) and css styles.
Cheers Romeo
You can pass in props using the slotProps
prop. Unfortunately, due to performance issues with TypeScript, if you pass in a custom slot component, the corresponding slotProps
won't have a related type. So if you do slots={{ root: MyFancyComponent }}
, the slotProps.root
won't expect the props of MyFancyComponent
and some casting may be necessary.
We are aware of the limitation of this API, and are currently working on improvements in this area. We plan to post an RFC soon and flesh out all the details of the new API.
Okay thats some clarity, but what about the InputCalculate
that I would like render instead of the input
slot from the NumberInput
?
What exactly do you have a problem with?
This should work:
<NumberInput slots={{ input: InputCalculate }} />
@michaldudak How can we pass parameters to InputCalculate <NumberInput slots={{ input: InputCalculate }} />
You can use slotProps:
<NumberInput slots={{ input: InputCalculate }} slotProps={{ input: { ... } }} />
What's the problem? π€
Before reading this RFC, please go through #34333 first so that we are on the same page about the meaning of
components
andslots
.From #33416, and #21453 it seems like we are only talking about slot override (replacing the slot). However, for Material UI and Joy UI, we also need a component override (changing the HTML tag of the slot).
What are the requirements? β
Proposed solution π’
My proposed solution aims for the least breaking changes. All components (MUI Base, Material UI, and Joy UI) should follow this:
Components with a single slot (
root
)component
(existing prop): for changing the root slot's HTML tag. (I think we should not drop this prop because it will be a huge breaking change)~For this kind of components, it does not make sense to replace the root slot so having just
component
prop is cleaner.~ This is not true for MUI Base π€.Components with more than one slot
component
(existing prop): for changing the subcomponent of the root slot (could be an HTML tag or React element).slots
andslotsProps
same as https://github.com/mui/material-ui/issues/33416slots.{slot}.component
: for changing the subcomponent of the target slot (could be an HTML tag or React element).To replace the HTML of the slot, use
slotsProps={{ listbox: { component: 'div' } }}
.Components that have nested components
See the problem and another example
Flatten the nested component slots with a new name. For example,
TextField
hasInput
as a nested component could look something like this: