create-class-names
A utility to extend the values of a classNames object.
Useful for global styles, css-modules, and css-in-js.
Why?
There is no clear way to extend classNames that are assigned to React Components.
{ const children = props; return <div className="container"> <span className="alert">⚠</span> /* I want to customize this text className! */ <div className="text">children</div> </div> ;}
An easy way to expose customizability is via an additional prop and using the classnames library.
{ const children textClassName = props; return <div className="container"> <span className="alert">⚠</span> <div className=>children</div> </div> ;}
However this approach doesn't scale well.
Use a theme object
A more structured way to solve this is to use a theme object.
{ const children theme = props; return <div className=themecontainer> <span className=themealert>⚠</span> <div className=themetext> <span className=themeinnerText>children</span> </div> </div> ;} BannerdefaultProps = theme: container: 'globalContainerClassName' ;
This allows parent componets to customize what classNames are given however it then becomes difficult to keep the default classNames.
const Page = <Banner theme= container: 'customContainerClass' /* This removes the default className */ />;
However keeping the default value is very cumbersome.
const Page = <Banner theme= container: ` customContainerClass` />;
That's where createClassNames
comes to the rescue!
Usage
const base = container: 'container'; // 1. This is essentially a shallow clone of base.const result = ; assert; // 2. Extend the base classNames.// If the extended values are not strings then they are ignored.const result = ; assert; // 3. Provide a default custom merge function.const result = ; assert; // 4. Provide a custom merge behavior per property.const result = ; assert;
Example
A more in depth example with React.
// With css-modules;const baseStyles = styles; // With global stylesconst baseStyles = container: 'container' alert: 'alert' text: 'text' // Empty string here because there is no base styles but you want // to allow parent components the ability to customize that element. innerText: ''; { const children theme = props; // Merges base and theme className values onto the same property. const theme = ; return <div className=themecontainer> <span className=themealert>⚠</span> <div className=themetext> <span className=themeinnerText>children</span> </div> </div> ;} const Page = /* Just uses default styles */ <Banner>Default Styles</Banner> /* Customizing classNames */ <Banner theme= container: 'secondBanner' alert: 'secondBannerAlert' innerText: 'secondBannerInnerText' > Custom Styles </Banner> /* If you pass a function as a value for a property then you can customize what resulting className is given. */ <Banner theme= { // baseStyleValue === 'container' // key === 'container' // result === the resulting theme object return 'secondBanner'; } > Over-riding container style </Banner>