mui / material-ui

Material UI: Comprehensive React component library that implements Google's Material Design. Free forever.
https://mui.com/material-ui/
MIT License
93.84k stars 32.25k forks source link

Add a "dummy" Mui-component processed in the custom them `overrides` prop to enable "targetting" without impacting layout #27143

Open EdmundsEcho opened 3 years ago

EdmundsEcho commented 3 years ago

The pain-point

I use the overrides prop a lot. In order to target a component there must be a Mui parent as the starting point for my selectors to latch-onto.

Sometimes, I have a component that uses "straight-up" React components encoded using plain-old html tags. As of now, I can't include this component in my custom theme. Of course I can "hack-it" using something like Container but that is not good design as it introduces a false intent.

The solution

In many programming languages there is the concept of the "identity function".

identity :: a -> a

The function outputs what was inputted. However, there is a related function with an important "extra": in a typed language the output might be "cast" to something that remains true to the identity value, but augments where the value can now operate (lifts the value).

pure :: a -> c a

... the idea:

muiTag :: html -> mui html

I propose a Mui component with no effect on the layout; i.e., does not distort/interact with the meaning of the child elements.

<MuiOverride className='My-Custom-Class'>
   <html-element />
</MuiOverride>

... where the MuiOverride -> html

<span class="MuiOverride My-Custom-Class">
   <html-element />
</span>

Note: while the name might seem heavy-handed, I chose it because it suggests using it with the overrides prop. While naming is important, the idea is not meant to hinge on it. e.g., <MuiId>, <MuiTag>, <MuiSpan> are others that come to mind.

Summary

Create a Mui component that generates a html element that does not change the layout (e.g., <span>. With support for this component, users can unify the configuration of their design under a single Mui banner.

Finally

Thank you for all of your efforts. The quality of this resource is top-tier.

mnajdova commented 3 years ago

You could use the styled() utility and provide a custom theme name for the component. Also, you can use the as prop, supported by both emotion/styled-components for changing the rendered HTML tag - https://emotion.sh/docs/styled#as-prop

Will this be sufficient for building this utility by yourself?

EdmundsEcho commented 3 years ago

Thank you for your response. I'm not familiar with styled(). I'll look into it.

In the meantime, may you confirm that it will work with the overrides prop or otherwise with the custom theme? I want to avoid using the useStyles() and the style prop locally on components. Do you know what I mean?

Update

I just looked at the link you sent. Unfortunately, using styled components is not an option. Unless I'm missing something (very possible :)), I can't see how it uses the custom theme approach. As far as I know, the only way to use the overrides prop is when the theme generator knows to look for specific props (i.e., supports overriding a given prop).

mnajdova commented 3 years ago

Take a look on this example - https://next.material-ui.com/system/styled/#custom-components The component is targeted via the MyThemeComponent name inside the theme's components object. You can add any overrides/styles for this component inside the theme.

EdmundsEcho commented 3 years ago

Thank you @mnajdova

We are getting close. The component has the class: class="css-41lojr-MyThemeComponent-root"

It seems to require styled components which isn't something my app supports. The primary location for the formatting is the custom theme overrides prop.

Is there a prop on the custom theme like the components prop that let's me include my own class names that are then "read-in" by the createTheme function?