Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/jamesknelson/react-c

An implementation of Pacomo, a system to help structure your React stylesheets.
https://github.com/jamesknelson/react-c

Last synced: 13 days ago
JSON representation

An implementation of Pacomo, a system to help structure your React stylesheets.

Awesome Lists containing this project

README

        

# react-c

**react-c** helps provides structure to your component's CSS. It does so by helping implement an application following the [Pacomo](https://github.com/jamesknelson/pacomo) guidelines for structuring React stylesheets. It provides two methods to help you write properly-scoped CSS classes, and an ES7 decorator to specify the package name.

With react-c, writing clean CSS for React is *so simple* that you no longer have any excuse to *not* do it.

## Example

The best way to understand react-c is to see it in action, so let's have a look how it is used in a slightly simplified copy of [numbat-ui](https://github.com/jamesknelson/numbat-ui)'s Paper component:

```JavaScript
import React from "react"
import c from "react-c"

@c("nui")
class Paper extends React.Component {
static propTypes = {
rounded: React.PropTypes.bool,
}

static defaultProps = {
rounded: true,
}

render() {
return (



{this.props.children}


)
}
}
```

Rendering a `Paper` component with the `rounded` property set to `true` will produce the following:

```html



...


```

This output in turn is styled using LESS or SCSS, using the `&-` selector to prevent Carpal Tunnel Syndrome:

```less
.nui-Paper {
//...

&-rounded {
//...
}

&-inner {
//...
}

&-rounded &-inner {
//...
}
}
```

## Usage

### 1. Install with NPM:

```JavaScript
npm install react-c --save
```

### 2. Import the module:

```JavaScript
import c from 'react-c' // ES6
```

*or*

```JavaScript
var c = require('react-c') // CommonJS
```

### 3. Add react-c to your component:

You have two options to do this. If you're building modules by extending `React.Component`, I recommend using ES7 decorators:

```JavaScript
@c("ns")
class MyComponent extends React.Component {
...
}
```

Otherwise, just pass your components to the `c(prefix)` manually:

```JavaScript
var MyComponent = React.createClass({
...
})

c("ns")(MyComponent)
```

### 4. Add classes to your components using `c` and `cRoot`

- `c(...)`

*Example output:* `'ns-MyComponent-a ns-MyComponent-b'`

Generates a `className` string using the [classnames](https://github.com/JedWatson/classnames) module, but with all classes prefixed with the component's name and specified prefix.

- `cRoot(initial, final)`

*Example output:* `'ns-MyComponent ns-MyComponent-initial this-prop-className ns-MyComponent-final'`

Returns the component name, followed by the result of passing `initial` and `final` parameters through `c(...)`, with the value of `this.props.className` (if any) sandwiched between.

As browsers give the later classes higher priority, it is possible to give your classes higher or lower priority than those added from `this.props.className`.

This function is generally used on the root component in your `render()` function, thus the name. You probably shouldn't use it more than once.

### 5. Write your LESS/SASS following the [Pacomo](https://github.com/jamesknelson/pacomo) guidelines.

Heres a short summary of the important parts - follow the link for the full specification.

1. Your component's stylesheet should have **exactly one** top level selector: the one generated by `cRoot`

Example:

```less
/* Good */
.MyComponent {
/* ... */
}

/* Bad */
.OtherComponent {
/* ... */
}

/* Bad */
#some-id {
/* ... */
}
```

2. All other selectors (and parts of selectors) should start with `&-`

Example:

```less
.MyComponent {
/* good */
&-inner &-input {
/* ... */
}

/* bad */
&-inner input {
/* ... */
}

/* good */
&-other-component {
/* ... */
}

/* bad */
.OtherComponent {
/* ... */
}
}
```

These two rules have a number of flow-on effects:

- You cannot select elements based on tag names or ids. Instead, select child elements by adding a class to them with `c`.
- You cannot directly apply styles to child components. Instead, pass in class names generated with `c` to child components, and style them instead.

The result of this is that it is incredibly easy to reason about what styles are applied, and where they come from. As a bonus, "inspect element" in your favourite web-browser will immediately show where styles originate.

## FAQ

### How do `c` and `cRoot` know what my class is called?

react-c uses `component.prototype.displayName || component.name` to decide what your component is called. This can break down in the following cases:

- You're using React.createClass, but not using JSX. This is because `component.prototype.displayName` is [set by the JSX compiler](https://facebook.github.io/react/docs/jsx-in-depth.html#the-transform). Set `displayName` manually in this case.
- You're applying the ES7 decorator *after* another decorator which modifies `component.name`. This can happen if it returns a `class` which extends the original, for example.

### Is react-c/Pacomo BEM compliant?

No.

BEM goes further than react-c, by distinguishing between classes for modifiers and elements.

For a BEM-based project, use something like [react-bem](https://github.com/cuzzo/react-bem).

### Why should I use react-c over BEM-based modules like react-bem?

Given most React components are very small and have limited scope, BEM is overkill in this context. If you find your components are getting big enough that you think it might make sense to distinguish between elements and modifiers (like BEM), you probably instead should focus on factoring your components into smaller parts.

## Related Projects

**react-c** is part of [react-base](https://github.com/jamesknelson/react-base) - a collection of Higher-Order Components to *make your life easier*.

**react-base** (and react-c) were extracted from [numbat-ui](https://github.com/jamesknelson/numbat-ui) - a collection of UI components for React based on Google's Material Design.

The actual guidelines are maintained in the [Pacomo](https://github.com/jamesknelson/pacomo) repository, independent of this implemention.