Establish a convention for extending the styles object at the runtime
gajus opened this issue · 3 comments
react-css-modules
uses styles
property to overwrite the default component styles.
generateClassName
could look for props.styles
and this.props.styles
when constructing the className
value to determine whether a style needs to be overwritten.
There could be an option to force use of generateClassName
even when styleName
is a string literal value.
I came up with a style like this that i'm extremely happy with
import cx from "classnames";
function mergeStyles(...styles) {
const style = {};
const cxStyle = cx.bind(style);
for (const sty of styles) {
if (!sty) {
continue;
}
for (const [key, val] of Object.entries(sty)) {
if (style[key]) {
style[key] += ' ' + val;
} else {
style[key] = val;
}
cxStyle[key] = style[key];
}
}
return cxStyle;
};
In my comp I then do
import styles from "./mainStyles.css";
import otherStyles from "./otherStyles.css";
this.styles = mergeStyles(styles, otherStyles /* additional styles*/, props.styles /* optional HOC style overrides*/);
Combining this with classnames, this lets me do:
<div className={this.styles.someClass}
<div className={this.styles('class1', {class2: false}, {class3: this.state.someState})}>
....
</div>
</div>
Then if the style is defined in the modules CSS, it uses the modularized now, else keep the original CSS label (see #47)
I feel like this takes the simplicity of this version of react modules and provides the same override power of the non babel version, bringing the best of both worlds.
It would be good if the styleName attribute was able to use a local scope styles property instead of the global one.
I tried overriding the global one by using import mainStyles at top and doing const styles = this.styles; to then use styleName, but that didn't work...
Thoughts?
Did you try using the classnames/bind pattern? This seems like a re-implementation of that same idea.
If that doesn't work with this, do you know why?
I hope this gets implemented, I need this functionality so I'm going to have to use react-css-modules
instead.