VulcanJS / vulcan-next

The Next starter for GraphQL developers
http://vulcan-docs.vercel.app
MIT License
393 stars 29 forks source link

Support 2 CSS patterns: Material UI and styled components VS styled-jsx, tailwind and postCSS #53

Open eric-burel opened 4 years ago

eric-burel commented 4 years ago

After exploring various styling approaches with Next, I came to the 2 following possible patterns

1. The CSS-in-JS approach: Material UI+ Styled Components Material UI v5 (emotion)

Why not material UI alone

makeStyles may induce performance issues, especially with TypeScript. Styled Components is a powerful CSS-in-JS replacement solution, officialy proposed as a replacement into the incoming v5 of Material UI.

Note: Emotion is probably also a valid candidate, but Styled Components is a bit simpler.

UPDATE MATERIAL UI V5: We have updated Material UI to V5, so using Emotion. This is still a beta version, we need to figure a few thing:

Limitations

You have to learn additional lib, and they add more complexity to your Next app. Some people strongly dislike CSS-in-JS

2. The purist approach: Styled-jsx and PostCSS, (+ bootstrap or tailwind or whatever CSS framework you like)

See official doc of built-in CSS support in Next

Why PostCSS

Styled-jsx is a very "raw" solution. It introduces CSS in React the right way, but without much additional feature. Nesting is a powerful feature, not included into styled-jsx. So in VNS we also bundle PostCSS.

~~### Why NOT CSS modules

They don't behave correctly with Storybook. However they are still included as a default in Next so if you don't bother about Storybook you can already use them in VNS. Edit: we now are able to use CSS modules in Storybook, it simply needs the right plugin.~~

Limitations

Styling child component leads to a poor syntax and requires wrapping with div or span. Basically, you can't restyle Material UI components easily.

Also, you can't setup VS Code with PostCSS + styled-jsx.

To be done: easy swap

Currently, we have both solutions preinstalled in VNS. In the future you should be able to enable only one of them. In particular, the Material UI + Styled components approach should be optional. We currently wait for plugins to be added to Next before investigating more.

https://github.com/vercel/next.js/discussions/9133

Edit: even better, we could mix Emotion and Tailwind: https://github.com/vercel/next.js/issues/23830

To be done: explore CSS modules

CSS modules didn't work in Storybook, until we figured the right package to support them. Now they work as expected so we may want to investigate them a bit more (ability to restyle existing components, syntax, should it be prefered to styled-jsx etc.).

oliviertassinari commented 4 years ago

Many people are going with 1.

eric-burel commented 3 years ago

Update in 2021: Material UI v5 will bring Emotion out-of-the-box, so approach 1 will be simplified (and that's excellent news).

For the "purist" approach, Tailwind seems to be appreciated a lot. Will it be a trend? Will see in a few months, I am testing it on personal project. First issue to handle: https://stackoverflow.com/questions/47607602/how-to-add-a-tailwind-css-rule-to-css-checker. We need to add stylelint as a recommended vs code package (in .vscode/extensions.json) + the right config to solve this (in .stylelintrc).

oliviertassinari commented 3 years ago

@eric-burel I would even say emotion (default) and styled-components out-of-the-box.

Inokcode commented 3 years ago

@eric-burel Hi I am about to start a project,and have few clarification,would u be able to tell me how can work with metrial ui and styled components together,bcz my main concern is we have to use typescript and start the project from webpack setup ,so do i need to install postcss for that ,and need to done testing also. 1)how to use typescript with MUI and styled components together(if any usefull link for learn this for big project pls attached) 2)Is it possible to run jest unit testing 3)do i need to install postcss for acive above task,how it goes with (1) 4)going to use monorepo design for the project 5)we are plan to use webpack from scrach not from CRA cmnd,so do i need postcss to insatll or css in js pluings(no idea) 6)how component reusing will help with (1)

so if anyone can guide me on this really appricatet it.

eric-burel commented 3 years ago

Hi @Inokcode, I'll try to answer your questions: 1) Just use it, for additional doc you should check Material UI documentation and Styled components documentation. Please note that we will probably soon change toward Emotion which is now the default for Material UI (but it works exactly like Styled Components no worries). 2) Yes it's all setup yarn run test:unit, @Timi-Duban just made a great PR so you can even differentiate server-only tests and client-only tests if necessary 3) PostCSS is already setup in the application, it will process Styled JSX content and CSS modules (the basic styling solutions from Next https://nextjs.org/docs/basic-features/built-in-css-support). I am not sure if there is something else to do with styled components. 4) I am not fond of true monorepos, like using Lerna in Next.js apps, because they are very complex. What's the use case? In Vulcan Next we "simulate" a monorepo using Webpack, so that the folders you create in packages can be imported within an app (it behaves like a monorepo, but it's simpler). 5) This is a Next.js framework, please stay in the "pit of success" => avoid fully custom webpack stuff. We don't use Create React App. 6) You should definitely take a look at styled components documentation and educational resources about component driven design and stuff like that

Inokcode commented 3 years ago

Hi @eric-burel I really appreciate the time taken for to reply for my questions, thank you for the quick reply.

eric-burel commented 3 years ago

For Material UI v5, we still need to check:

Using strings seems to make syntax highlighting complicated, Styled Components plugin is still full of bugs after many years. Using JS objects is maybe more suited, as most UI development languages DON'T have a thing like CSS and are pretty happy without it.

ptolideh commented 2 years ago

Hey @eric-burel ,

I'm coming from this thread: https://github.com/vercel/styled-jsx/issues/142

Do you still think it's still worth it to customize MaterialUI V5 using Styled-JSX?

I got styled-jsx working actually without a wrapper -- Installing "styled-jsx-plugin-sass" did the trick, but requires a unique className to locally scope it:

      <>
        <Button className="BasicButton" variant="contained">Test</Button>
        <style jsx>{`
           :global(.BasicButton.MuiButton-root) {
              box-shadow: none;

              &:hover {
                background-color: red;
              }
            }
          `}</style>
      </>
eric-burel commented 2 years ago

Hi, this PR will bring the final Mui v5 update: https://github.com/VulcanJS/vulcan-next/pull/124, I'll merge it in a few days.

If you are going to use Material UI, then no, I would use their own styling approach. I didn't like Mui v4 styling solution, but v5 is way better. If you really want a CSS-ish syntax, you can directly use Emotion, since Mui is based on it, it works perfect.

I would keep Styled JSX for simpler apps with more design (typically landing pages, blogs...), when you don't want to use an existing UI lib.

ptolideh commented 2 years ago

@eric-burel Thanks Eric. Makes sense. Mui v5 is definitely a great upgrade, I also wasn't a fan of JSS. Wish they supported Tag Functions tho. Writing CSS syntax always feels more natural than object-style

eric-burel commented 2 years ago

They still use the JSON syntax. However I think you can keep using Emotion as usual if you want to avoid that, only thing you'll miss will be the helpers provided by Material UI + "magic" link with the theme (you'll have to call useTheme). In Vulcan Next I'm still hesitant. Right now I use the default JSON syntax for the demo components but that could change, I also like string CSS.

eric-burel commented 2 years ago

Some tools that could help writing unstyled components: