uber / react-vis

Data Visualization Components
https://uber.github.io/react-vis
MIT License
8.72k stars 834 forks source link

RFC Drop scss in favor of styled-components #823

Open mcnuttandrew opened 6 years ago

mcnuttandrew commented 6 years ago

As anyone familiar with this github repo is aware, one of the most frequent bugs folks encounter is not importing the styles. As anyone familiar with developing in this project is aware, a frequent annoyance is rebuilding node-sass all of the time.

I propose that we address these problems by rewriting the style sheet as a collection of minimal styled components. There is a modest amount of cruft in the the style sheets which could easily be taken out in this process. I like the library called styled-components, but i'd be open to other solutions as well.

Interested to hear comments!

lzhuor commented 6 years ago

+1 👍

To migrate to styled-components, 5 wrappers are needed:

mcnuttandrew commented 6 years ago

I'm not sure the examples page needs to be moved to styled-components. Like it is lowest priority as it is not externally consumed.

lzhuor commented 6 years ago

Hi @mcnuttandrew , I agree that Examples Page is not externally consumed and can be put as the lowest priority. Re-arranged its order.

The reason why I put it on the TODO list is that examples.scss consumes a few variables imported from main.scss.

For example:

&.left-bottomEdge {
        border-left: 2px solid $hint-color;
        left: -1px;
        height: $margin-bottom;
        width: 0;
        top: -$margin-bottom;
      }

$margin-bottom and $hint-color are used directly as an imported var. If we would like to remove main.scss together with plot.scss etc., we probably have to migrate examples.scss or we can dump all SCSS variables into examples.scss to resolve the issue.

jckr commented 6 years ago

Hey Andrew,

IMO, css-in-js solutions like styled-components and stylesheets based solutions like scss are not exclusive.

In the context of react-vis, which can potentially create thousands of DOM elements, css is likely to be more performant than inline styles. Another thing in favor of a css solution is that it's always possible to override css with css, and often with injected styles if the right properties are exposed. Conversely, it's not always possible to override inline styles with css and/or with injected styles. Finally, a great side effect of using css is that DOM elements get classes which are helpful for testing. Now a major issue for a css-based solution is that css/scss needs to be imported, which is often, at least, impractical. It can also be argued that inline styles are more consistent with the spirit of React.

With that in mind, a good solution:

Though we could go even further and let people completely reskin their charts with a consistent theme without having to manually override dozens of individual rules.

With that in mind, the direction I was considering is:

XYPlot can take a theme prop which is a json object where properties are either css rules or correspond to the class of an XYPlot element. ie:

{ 
  fontFamily: "serif",
  lineSeries: {
    stroke: "black"
  }
}

XYPlot would then pass this theme prop to its children. The children will then take this theme into account when styling (ie explicit style prop > other props > theme prop > css rules).

Further, react-vis will propose:

lzhuor commented 6 years ago

Hi @jckr and @mcnuttandrew ,

How about importing SCSS into the components directly with webpack scss loader?

Example:

ContinuousColorLegend component:

import '../styles/legend.scss';

It resolves the problem where user forgets to import scss but doesn't necessarily require styled-components.

jckr commented 6 years ago

This already works but on webpack. We can't force anyone who wants to use react-vis to use webpack (i mean we could, but I don't think we should)

mcnuttandrew commented 6 years ago

Many thoughts!

jckr commented 6 years ago

we have strong proponents of styled-components at Uber. kepler.gl for instance uses them extensively.

an additional aspect of the future system which isn't too expensive to consider is component injection. We could have something like <XAxis components={{AxisTitle: MyAxisTitle}} /> where MyAxisTitle replaces AxisTitle for all intents and purposes. MyAxisTitle could be a completely new component, or just be a styled version of AxisTitle.

mcnuttandrew commented 6 years ago

Should this process be undertaken it would be a good moment to develop a snapshot testing. Having seen the wonders of puppeteer, I can testify that it's kinda easy to do snap shot testing now, and we should be doing it. So if were were to execute a css-in-js strategy a plan of attack would be like:

  1. Write tests to verify the look and feel of all components (single snapshot per showcase item would be fine)
  2. Transition scss styles to styled components
  3. Release and bug catch
wangzuo commented 5 years ago

I have created react-vis-styles to help me avoid bundling css.