A tiny library to easy apply css/styles to react components with zero references to your css classes or to inline-styles.
npm install react-easy-style
you'll need also:
webpack
, css-loader
, react
The React community is highly fragmented when it comes to styling. Right now, there is more then 16 project for inline css on the github, all of they are trying to fix some "issue" that css has, like global scope... but, I think, they all are creating a lot of new one as well.
React Easy Style "borrow" ideas from one of those projects: react-css (1). And join it with webpack css-loader (2) to make a very light and useful library to easy use classes and styles on react components.
-
react-css: seems to be the only one to have noticed that style and react props/state are strong linked to each other.
-
webpack css-loader: with support to CSS Module spec that fix css global scope issue.
Take a look!
// button.jsx
import React from 'react'
import EasyStyle from 'react-easy-style'
// import css/scss/less with webpack css-loader
// webpack.config sample loaders: [{test: /\.scss$/, loader: "style!css!sass" }]
import css from './button.scss'
@EasyStyle( css )
export default class Button extends React.Component {
static defaultProps = {
kind: 'default', circle: false
}
render() {
return <button>{ this.props.label }</button>
}
}
// if you don't use decorators:
// class Button extends React.component { ... }
// export default EasyStyle(css)(Button)
// button.scss
:local .Button {
border: 1px solid transparent;
// a lot of other styles
// browser state rules
&:focus { outline: none; }
// React props/state rules
// pattern: className--propsKey-propsValue
&--circle-true { border-radius: 50% }
&--kind-default { /*...*/ }
&--kind-primary { /*...*/ }
&--kind-success { /*...*/ }
}
And that is it. Seriously! For small/medium components you will end up with 0 (zero) css references on you code.
Here a example of how to call it and its output:
// when you call
<Button kind='primary' circle={true} label='...'/>
// ... you'll receive this final html
<button class='Button Button--kind-primary Button--circle-true'>...</button>
// ps.: On real world, css-modules will change classes names
// to make they unique (no more global namespace!), something like:
<button class='jduei3dfu3d_Kjm jduei3dfu3d_Kjm-2e jduei3dfu3d_Kjm-43'>...</button>
For more complex components, please, keep reading ;-)
class Button extends React.Component {
render() {
return (
<button className='in1 in2'>{this.props.label}</button>
)
}
}
// call
<Button kind='primary' className='out1 ou2' label='...'/>
// html output
<button class='Button Button--kind-primary in1 in2 out1 out2'>...</button>
class Button extends React.Component {
render() {
return (
<button>
<span is='label'>{this.props.label}</span>
<span is='desc'>{this.props.desc}</span>
</button>
)
}
}
// call
<Button kind='primary' label='...' desc='...' />
// html output
// don't forget, with css-modules, label and desc class names will receive unique names
// so... using a generic name like 'label' isn't a issue
<button class='Button Button--kind-primary'>
<span class='label'>...</span>
<span class='desc'>...</span>
</button>
// button.scss
:local .Button {
.label { color: #000 }
.desc { font-size: 85% }
// and into your states...
.&--kind-primary .label {}
.&--kind-primary .desc {}
}
class Button extends React.Component {
render() {
return (
<button>
<span is='label'>{this.props.label}</span>
<span is='desc' className='in1 in2' style={{fontSize:12}}>{this.props.desc}</span>
</button>
)
}
}
// call
<Button kind='primary' label='...' desc='...' />
// html output
<button class='Button Button--kind-primary'>
<span class='label'>...</span>
<span class='desc in1 in2' style='font-size: 12px'>...</span>
</button>
To nested elements that use, for example, is='label' you'll have labelClasses='class1' and labelStyle={{...}}. for top-level element (root) you have rootClasses, rootStyle, className and style. In another word: Themeable for free.
class Button extends React.Component {
render() {
return (
<button>
<span is='label'>{this.props.label}</span>
<span is='desc'>{this.props.desc}</span>
</button>
)
}
}
// call
// ps.: for root you can use className/style or rootClasses/rootStyle or both ;)
// all styles will be merged
<Button
labelClasses='lb1 lb2'
labelStyle={{marginLeft: 10}}
rootClasses='rt1'
className='cn1'
style={{padding: 2}}
kind='primary' label='...' desc='...' />
// html output
<button class='Button Button--kind-primary rt1 cn1' style='padding: 2px'>
<span class='label lb1 lb2' style='margin-left: 10px'>...</span>
<span class='desc'>...</span>
</button>
class Button extends React.Component {
render() {
return (
<ToolTip><button is='root'>...</button></ToolTip>
)
}
}
// call
<Button kind='primary' label='...' />
//output
<div class='from-tooltip'>
<button class='Button Button--kind-primary'>...</button>
</div>
By default Easy Style will try to find a class with same name of component, or one called 'root'. But you can pass a new one.
// grid.jsx
@EasyStyle(css, 'myContainer')
class Container extends React.Component {}
// grid.scss
// easy style will find classes in this order (and use the first found):
:local .myContainer { /** ... **/ }
:local .Container { /** ... **/ }
:local .root { /** ... **/ }
Ok, React Easy Style has support to inline styles BUT without fancy feature like browser state or media queries. Let's see:
const style = {
base: {
root: { padding: 2, /**...**/ },
label: { /**...**/ },
desc: { /**...**/ }
},
'kind-primary': {
root: { /**...**/ },
label: { /**...**/ },
desc: { /**...**/ }
},
'circle-true': {
root: { /**...**/ },
label: { /**...**/ },
desc: { /**...**/ }
}
}
@EasyStyle( style )
export default class Button extends React.Component {
static defaultProps = {
kind: 'primary'
}
render() {
return (
<button>
<span is='label'>{this.props.label}</span>
<span is='desc'>{this.props.desc}</span>
</button>
)
}
}
// and it just works.
// and you can use rootClasses, rootStyle, labelStyle, labelClasses, etc...
Implement tests ;)- Benchmark performance (it's very fast, but maybe it can be more)
- Support themes, maybe using react context
If you like it, please help!!