Ease the adoption of CSS Modules
inside create-react-app
https://facebook.github.io/create-react-app/docs/adding-a-css-modules-stylesheet
Documentations of CSS Modules
talk about how we must use className
s in camelCase
https://github.com/gajus/react-css-modules, unless using styleName
as provided by babel
plugin https://github.com/gajus/babel-plugin-react-css-modules.
But with styles-of
(just a simple helper function really), it is easy to support any CSS className
s, and by the same token make use of multiple className
s & conditional formatting of className
s a breeze, or at least as painless as possible.
Let's use the same CSS Modules
example as the one used in both links above:
import React from 'react';
import styles from './table.css';
export default class Table extends React.Component {
render() {
return (
<div className={styles.table}>
<div className={styles.row}>
<div className={styles.cell}>A0</div>
<div className={styles.cell}>B0</div>
</div>
</div>
);
}
}
import React from 'react';
import styles from './table.css';
import stylesOf from 'styles-of';
const _of = stylesOf(styles);
export default class Table extends React.Component {
render() {
return (
<div className={_of('table')}>
<div className={_of('row')}>
<div className={_of('cell')}>A0</div>
<div className={_of('cell')}>B0</div>
</div>
</div>
);
}
}
OK, we've replaced styles.xyx
by _of('xyz')
, not necessary a fantastic trade-of, but wait, the use of styles-of
makes a lot more sense with the more complex composition of className
s.
Let's say for the first cell
A0 we want to use another className, say cell-first
.
Without styles-of
:
<div className={styles['cell-first']}>A0</div>
With styles-of
:
<div className={_of['cell-first']}>A0</div>
Pretty much a tie there.
Or maybe even some conditional logical when inside a loop say, for styling the first row
differently.
Without styles-of
:
<div className={styles.table}>
{rows.map((row, index) => (
<div className={`${styles.row} ${index ? '' : styles.first}`}>
{...}
</div>
)}
</div>
With styles-of
:
<div className={styles.table}>
{rows.map((row, index) => (
<div className={_of('row', index ? '' : 'first')}>
{...}
</div>
)}
</div>
You get the picture ;-)
As we can see, the more complex the expressions to compose the className
, the more using styles-of
makes sense.
But for my personal use, the ultimate use case was:
Without CSS Modules
:
import React from 'react';
export default class Table extends React.Component {
const rows = [...];
render() {
return (
<div className="table">
{rows.map((row, index) => (
<div className={`row ${index ? '' : 'first'}`}>
{...}
</div>
)}
</div>
);
}
}
With CSS Modules
with styles-of
:
import React from 'react';
export default class Table extends React.Component {
const rows = [...];
render() {
return (
<div className={_of("table")}>
{rows.map((row, index) => (
<div className={_of(`row ${index ? '' : 'first'}`)}>
{...}
</div>
)}
</div>
);
}
}
So the conversion is quite simple: change className="xyz"
to className={_of("xyz")}
(add {_of()}
), whereas without styles-of
, it maybe less straight forward for conditional className
s and such cases:
With CSS Modules
without styles-of
:
import React from 'react';
import styles from './table.css';
export default class Table extends React.Component {
const rows = [...];
render() {
return (
<div className={styles.table}>
{rows.map((row, index) => (
<div className={`${styles.row} ${index ? '' : styles.first}`}>
{...}
</div>
)}
</div>
);
}
}
styles-of
supports 2 different call styles:
- currying:
stylesOf(styles)('classA classB');
- direct:
stylesOf(styles, 'classA classB');
It is presumed that the currying call style is the preferred way so it is slightly more optimized.
For each call style, 3 different argument types are supported:
- one space delimited string:
stylesOf(styles)('classA classB'); // currying
stylesOf(styles, 'classA classB'); // direct
- one array of strings:
stylesOf(styles)(['classA', 'classB']); // currying
stylesOf(styles, ['classA', 'classB']); // direct
- variable string arguments:
stylesOf(styles)('classA', 'classB'); // currying
stylesOf(styles, 'classA', 'classB'); // direct