Material UI has the exact same Box component, also using styled-system.
They're both libraries of components, so just as much a "nightmare" to extend or integrate.
Seems the biggest difference is this uses Emotion.
Material UI implements Material UI by default and this is the main reason why it's hard to customize. Too much to change. I guess this is one of the reasons why there are not that many custom themes available for this library.
If you spend sometime with Material UI you will realize that it is actually designed really well.
[1]: https://material-ui.com/api/input-base/ [2]: https://material-ui.com/api/button-base/
Also, since when does LOC say anything about developer productivity? By using Material UI you are avoiding a lot of problems that you will face later on especially if you are building a complex app.
But anyway, it looks like we have had different experiences, maybe due to different use cases. My experience with Material UI has been the opposite of yours: It is cool to get a quick project stated, and I would use it again for small projects. But for a large SaaS application like I do, that includes 3D views, Openlayers Maps, React Select and others complicated 3rd party libraries and custom UX patterns, I would NOT use Material UI. Too opinionated, not flexible enough, and not being based on emotion is a show stopper for me. So let's agree to disagree maybe on that point.
Regarding the LOC, yes it does indeed say something about developer productivity, and this does match the contortions I had to do in the past to make Material UI fit my need. Lot of LOC, lot of time, no-so-cool results. I want more control, that's all.
==========================================
Chakra: 215 lines
https://github.com/chakra-ui/chakra-ui/blob/master/packages/...
Typical comment line in chakra is clear and useful:
"If added, the button will show an icon after the button's label"
==========================================
Material: 415 lines with a lot of boilerplate:
https://github.com/mui-org/material-ui/blob/master/packages/...
Typical comment line in material is redundant and overly specific:
Styles applied to the root element if `size="large"` and `variant="outlined"`
So for complex components like TextField which has an InputLabel, Input and FormHelper component you have corresponding props: InputLabelProps, InputProps and FormHelperProps which accepts a `classes` prop each. You can then create ad-hoc CSS-in-JS styles using makeStyle and pass them as classnames to the respective inner-components `classes` prop. You'll realize the advantage of this only when you try it out.
Here is a quick example I created for you to try: https://codesandbox.io/s/material-demo-d2vmn?file=/demo.js:2...
The left side is a normal TextField and the right side is a TextField with styles overridden. If you do not like the TextField component Material UI provides you can always create your own with InputBase component.
Edit: Hacker News isn't letting me post a comment to your comment so I am editing my comment here.
Your example doesn't match mine. It just styles the component itself. Not inner components. For that you need a uniform API which neither Emotion nor Chakra provide. Please see my example again. The TextField component is a complex component comprising of InputLabel, Input and FormHelper. The idea is to style those inner components without actually breaking apart the source. We need a uniform API for that and neither Emotion nor Chakra provide something along those lines. Which is the crux of the argument on why Material UI is superior. It not only provides CSS-in-JS styling options like Emotion but also provides a standard API to style inner components no matter how deep in the tree they are. If you want to replicate the same feature you would have to create your own abstraction. But then that abstraction is not on the library level but your application level.
So if someone wants to work on your app, they will have to learn your abstraction first. If they move on to another app they can't carry over your abstraction in case the other app doesn't have the same implementation. They will either have to learn the new implementation or create that abstraction from scratch leading to a lot of bloat.
If I know some project is using Material UI I feel comfortable knowing that the API to modify a component and its inner components will be the same. That gives me a lot of confidence.
I made there an example matching yours: https://codesandbox.io/s/chakra-demo-upcrp?file=/src/app.js
So if someone wants to work on your app, they will have to learn your abstraction first. If they move on to another app they can't carry over your abstraction in case the other app doesn't have the same implementation. They will either have to learn the new implementation or create that abstraction from scratch leading to a lot of bloat.
If I know some project is using Material UI I feel comfortable knowing that the API to modify a component and its inner components will be the same. That gives me a lot of confidence.
I agree my example is simpler than yours, but you will also agree that it is functionally equivalent.
My example takes 8LOC of customization. Yours use 45LOC. That matches my experience with customizing styles on larger project, Chakra is 80% simpler to customize.
Material UI in general is more complex and more opinionated (why do Input boxes Have to have this weird animated description? That’s opinionated) Which is why I prefer Chakra. KISS.
We are not changing CSS alone here. You can do nested CSS styles through Material UI too. But that doesn't make any sense when you have complex components.
If you are relying only on CSS styling then you are tightly coupling the implementation with presentation. Say you have a nested button that is an <input type="button"> in one component. So your nested CSS style in another component that includes this button component would be: "> input[type=button]". Now tomorrow, some developer on your team decides to change the implementation to <button> instead as it is more semantic. Then what happens? All places that have your CSS nested style goes out of whack because of this one change. Because you have hardcoded your nesting. You will then have to change all references from "> input[type=button]" to "> button" just to meet the change in the implementation detail.
What is the point of CSS-in-JS if you are going to use CSS nested selectors for inner components? You might as well just use CSS modules instead. If you want to do CSS-in-JS do it the right way. Use JS to expose APIs for your components and CSS to style those components by reference. That way your components are truly independent of each other. Right now with Emotion, changing styles for your nested component implies using nested selectors which makes your components tightly coupled.
Now let us make it more complex: What if you want to introduce a <div> in between your parent component and the nested <button> component, as a wrapper? Not only do you have to change your JS implementation but also change all nested selectors from "> button" to "> div > button". It is a big mess at this point!
With Material UI it doesn't matter what your implementation is. Your component can use an input[type=button] or button or heck a div that behaves like a button using ARIA roles. It can even be nested 10 levels deep. You can even swap it out with links and it won't fail. Because styling is applied through a JS interface rather than CSS nested selectors. The implementation takes care of where to apply the styles. For the person outside he is just changing the style of the inner component without knowing how it is implemented. That is the real beauty of CSS-in-JS. Not knowing implementation detail ahead of time.
We are using CSS-in-JS because of limitations of CSS: you can't define custom components in CSS. If you are going to do traditional CSS with nested selectors using CSS-in-JS then you are just doing it wrong! You don't even need CSS-in-JS at this point apart from it being just a convenience. You can just use CSS modules or regular stylesheets.
https://styled-system.com/variants
you can use it in Chakra or in anything else that supports this spec.
Variants are defined by the implementor of the component in question. What I am talking about is overriding styles by the user of the component. One way to do it is through the ThemeProvider. But that does so globally. If I want to override a style for a particular component only in one place (and the nested components within it) then I will have to use CSS nested selectors or a nested ThemeProvider (which is hacky and ends up slowing down the app depending on how it is implemented). Then I am tightly coupling the implementation with the presentation. There is no API as such to change the nested component styles directly. That is the area where I feel Material UI does better. It has standardized how inner components are exposed to the World for styling. That standardization should happen at the library level instead of at application level. So whenever you import the library you know you have that option available to you too.
Please take a look at theme spec where variants become part of your theme object. You use theme.js to provide custom variants to components. This is how you would let users to customize your components via well defined expressed API (typed with TS if you want) :-)
> One way to do it is through the ThemeProvider. But that does so globally.
You can have as many nested ThemeProviders as you want. This is not a hacky way but is the way if for some reason it's not enough for you to have 1 global theme object.
Material UI is great for what it does (implements said kind of design) but if material design is not what you want then using this library with its own layers of abstraction is a no go to me.
It looks like Material UI has its own implementation of styled-system which is great! They should have started with something like that from the start :-)
Since your contention was the LOC and ability to use nested CSS styles, I have taken your own example and matched it. Line to line. Using Material UI. Updated the above demo:
https://codesandbox.io/s/material-demo-d2vmn?file=/demo.js:1...
8 LOC of customization. Same styles you applied to your demo with a few syntactic changes.
Hope this convinces you that you can do exactly the same thing in Material UI as you can in Chakra. Because both use CSS-in-JS. What you can't do in Chakra is ability to change styles of nested components (note I am saying components instead of HTML elements) without worrying about implementation detail.