https://github.com/jamesknelson/react-cx
Combine styles from CSS Modules with a `cx` prop.
https://github.com/jamesknelson/react-cx
css react style
Last synced: about 1 year ago
JSON representation
Combine styles from CSS Modules with a `cx` prop.
- Host: GitHub
- URL: https://github.com/jamesknelson/react-cx
- Owner: jamesknelson
- License: mit
- Created: 2017-09-22T03:11:27.000Z (almost 9 years ago)
- Default Branch: master
- Last Pushed: 2017-12-27T09:32:57.000Z (over 8 years ago)
- Last Synced: 2025-03-23T01:35:48.614Z (over 1 year ago)
- Topics: css, react, style
- Language: JavaScript
- Homepage:
- Size: 35.2 KB
- Stars: 23
- Watchers: 3
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
react-cx
========
[](https://www.npmjs.org/package/react-cx)
Add styles from CSS Modules with a `cx` prop:
```jsx
```
Inspired by [jareware/css-ns](https://github.com/jareware/css-ns). Uses [jedwatson/classnames](https://github.com/JedWatson/classnames) under the hood.
Install with npm:
```sh
# Adds react-cx to node_modules and package.json
npm install react-cx --save
```
Why?
----
When styling components with [CSS modules](https://github.com/css-modules/css-modules), you'll often need join multiple class names together before passing them to the React `className` prop.
```jsx
// CSS Modules provide an object with your stylesheet's class names
import styles from './Theme.less'
export function({ active, className, color, length=1 }) {
const className = `
${styles.Arrow}
${active ? styles.active : ''}
${styles[color] || ''}
${styles['length-+'length] || ''}
${className}
`
}
```
The [classnames](https://github.com/JedWatson/classnames) package can help, but the resulting code still feels a little verbose after you've typed it for the 50th time.
```jsx
import styles from './Theme.less'
// classnames provides a helper to build `className` strings
import bindClassNames from 'classnames/bind'
const cx = bindClassNames(styles)
export function Arrow({ active, className='', color, length=1 }) {
return
}
```
With react-cx, you can add styles from your CSS modules directly to your elements by using the `cx` prop. It uses the same syntax as the classnames package, and still lets you append a raw `className` prop.
```jsx
import styles from './Theme.less'
// react-cx adds a `cx` prop to React by wrapping `React.createElement`
import getReactWithCX from './react-cx'
const React = getReactWithCX(styles)
export function Arrow({ active, className, color, length=1 }) {
return (
)
}
```
Of course, the `cx` prop can also accept strings or plain objects:
```jsx
export function Switch({ active, className, color='lifecycle', direction='down' }) {
return (
)
}
```
*These components are taken from my [React lifecycle simulators](https://reactarmory.com/guides/lifecycle-simulators).*
How does it work?
-----------------
In React, JSX calls are translated to calls to `React.createElement()`. Thus, by wrapping `React.createElement()` with our own function, we can add support for new props without ever touching React's internals.
If you understand how `React.createElement()` works, the easiest way to grok this is to just view the source below. If you're not yet familiar with `React.createElement()`, head over to [React Armory](https://reactarmory.com/guides/learn-react-by-itself/react-basics) for a simple explanation with live examples and exercises.
```js
import UnprefixedReact from 'react'
import classnames from 'classnames/bind'
export default function cx(styles, prop='cx') {
const bound = classnames.bind(styles)
function getProps(props) {
if (!props) return props
if (props.cx) {
const result = Object.assign({}, props)
delete result.cx
const args = Array.isArray(props.cx) ? props.cx : [props.cx]
result.className = bound(...args)
if (props.className) result.className += ' '+props.className
return result
}
return props
}
function createElement(type, props, ...children) {
return UnprefixedReact.createElement(type, getProps(props), ...children)
}
function cloneElement(element, props, ...children) {
return UnprefixedReact.cloneElement(element, getProps(props), ...children)
}
return Object.assign({}, UnprefixedReact, {
createElement,
cloneElement
})
}
```
More examples
-------------
These components are all taken from my [React lifecycle simulators](https://reactarmory.com/guides/lifecycle-simulators).
```jsx
export function Indicator({ active, className, color, icon, label, noMobile, scheduled, style }) {
return (
{ icon &&
{icon}
}
{label}
)
}
export function Switch({ active, className, color='lifecycle', direction='down', style }) {
return (
)
}
function SwitchedSetter({ className, color, icon, label, noMobile, setActive, style, switchActive, willSet }) {
return (
)
}
```
License
-------
[MIT](/LICENSE) Copyright © 2017 James K Nelson