An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

          

react-cx
========

[![Version](http://img.shields.io/npm/v/react-cx.svg)](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