Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/diegohaz/singel

Single Element Pattern
https://github.com/diegohaz/singel

cli linter react react-patterns reactjs

Last synced: about 1 month ago
JSON representation

Single Element Pattern

Awesome Lists containing this project

README

        

# singel

[![Generated with nod](https://img.shields.io/badge/generator-nod-2196F3.svg?style=flat-square)](https://github.com/diegohaz/nod)
[![NPM version](https://img.shields.io/npm/v/singel.svg?style=flat-square)](https://npmjs.org/package/singel)
[![Build Status](https://img.shields.io/travis/diegohaz/singel/master.svg?style=flat-square)](https://travis-ci.org/diegohaz/singel) [![Coverage Status](https://img.shields.io/codecov/c/github/diegohaz/singel/master.svg?style=flat-square)](https://codecov.io/gh/diegohaz/singel/branch/master)

**Single Element Pattern** (Singel) is a set of rules/best practices to create consistent, reliable and maintainable components in React and other component-based libraries. This is based on the idea that the **building blocks** of an application should resemble as most as possible native HTML elements. [**Read full article**](https://medium.freecodecamp.org/introducing-the-single-element-pattern-dfbd2c295c5d)

This repo is a CLI tool for checking whether React components conform to the Singel pattern.



Example


## Installation

```sh
$ npm i -g singel
```

## Usage

```sh
$ singel path/to/**/Component.js --ignore "path/to/**/ignored/Component.js"
```

## Projects applying Singel

> Feel free to send a PR adding your open source project

- [Reakit](https://github.com/diegohaz/reakit)

## Rules

### Render only one element

```jsx
// bad - 2 elements
const Element = props => (




);

// good
const Element = props => (


);

// good - if Element is good
const Element2 = props => (

);
```

### Never break the app

```jsx
// good
const Element = props => (


);

// bad - will break if getId wasn't provided
const Element = ({ getId, ...props }) => (


);

// bad - will break if foo wasn't provided
const Element = ({ foo, ...props }) => (


);
```

### Render all HTML attributes passed as props

```jsx
// good
const Element = props => (


);

// bad - not rendering id
const Element = ({ id, ...props }) => (


);

// good
const Element = ({ id, ...props }) => (


);
```

### Always merge the styles passed as props

```jsx
// good
const Element = props => (


);

// bad - not rendering className
const Element = ({ className, ...props }) => (


);

// bad - not rendering style
const Element = ({ style, ...props }) => (


);

// bad - replacing className instead of appending
const Element = props => (


);

// bad - replacing style instead of merging
const Element = props => (


);

// good
const Element = ({ className, ...props }) => (


);

// good
const Element = ({ style, ...props }) => (


);
```

### Add all the event handlers passed as props

```jsx
// good
const Element = props => (


);

// bad - not passing onClick
const Element = ({ onClick, ...props }) => (


);

// bad - replacing onClick prop
const Element = props => (


);

// good
const Element = ({ onClick, ...props }) => (


);

// good - it's ok to replace internal event handlers
const Element = props => (


);

// good - calling internal and prop
const callAll = (...fns) => (...args) =>
fns.forEach(fn => fn && fn(...args));

const Element = ({ onClick, ...props }) => (


);
```

## FAQ

### How to handle nested elements?

Say you have a `Button` element and you want to display a `Tooltip` when it's hovered. The first rule you'll want to break is rendering only one element. To handle that you have some options:

- Use CSS pseudo-elements (such as `:after` and `:before`);
- Create a non-singel element, which is fine;
- Nest styles instead of components.

Here's an example of how you can accomplish tha latter one:

```css
/* could also be CSS-in-JS */
.button {
position: relative;
/* more button css */
}

.button:hover .tooltip {
display: block;
}

.button .tooltip {
display: none;
position: absolute;
/* more tooltip css */
}
```

```jsx
const Button = ({ className, ...props }) => (

);

Button.Tooltip = ({ className, ...props }) => (


);
```

Usage:

```jsx


😁

Hover me

```

Both `Button` and `Button.Tooltip` are single elements. You have all the benefits you would have by nesting them, but now with complete control over `Button.Tooltip` from outside.

## License

MIT © [Diego Haz](https://github.com/diegohaz)