cxs-css / cxs

fast af css-in-js in 0.7kb
MIT License
1.19k stars 68 forks source link

plugin system #84

Open souporserious opened 7 years ago

souporserious commented 7 years ago

Since you've moved away from glamor, I was curious if you would be willing to support a plugin system similar to theirs?

I do something similar to your styled-system library with glamor's plugin system right now:

const designSystemPlugins = [
  flex,
  position,
  size,
  space,
  border,
  typography,
  color,
  elevation,
  misc,
  fixVerticalRhythm,
]

designSystemPlugins.forEach(func => {
  glamor.plugins.add(({ selector, style }) => ({
    selector,
    style: func(style),
  }))
})

It would be awesome if we could do something like this with CXS, where any value I pass like cxs({ elevation: 2 }) would know how to get resolved. This would be similar to something like PostCSS where you can parse styles in one spot and not have to import them every time. I think this could also help with vendor prefixing and being able to handle this in one spot as well.

jxnblk commented 7 years ago

Interesting... I've definitely experimented with a similar approach before, but ultimately felt strange to allow for different/non-standard style objects to be passed to the core function, and that's why I'm leaning more towards wrapping functions like styled-system. Although the common use case for styled-system is with React props, it can also work at a lower level like this:

import cxs from 'cxs'
import { color } from 'style-system'
const styles = {
  color: 'white',
  bg: 'blue'
}
const className = cxs(color(styles))

Which in my mind, would achieve the same thing, right? (I haven't really looked at the implementation for glamor)

If you did want to add a pluggable version of cxs, I think it could be achieved like this, which could be exposed as cxs/plugins without affecting the core part of cxs

const pluggable = funcs => customStyle => {
  const styles = funcs
    .map(f => f(customStyle))
  return cxs(...styles)
}

Then using the plugin version:

import createCXS from 'cxs/plugins'

const cxs = createCXS([ fontSize, width, space, color ])

Does that make sense or am I totally missing something?

souporserious commented 7 years ago

Nope, totally makes sense! I love the pluggable idea, since it'd be nice to have an official way to do it :) I also like that's it not adding bloat to the core and seems very explicit compared to setting an internal option somewhere. I can create a PR if you'd like? Please let me know.

Jascha-Sundaresan commented 7 years ago

this approach wouldn't benefit from cxs's deduplication.

by exposing rx to be overwritten w/ a custom function like in #93, the plugins are only called when they encounter new style rules, and the output of the plugin wouldn't get stored in cxs's cache.