/react-bem-helper

BEM library for React

Primary LanguageJavaScriptMIT LicenseMIT

react-bem-helper

BEM library for React

NPM Version Build Status Coverage Status Bundle size

Table of Contents

Installation

$ npm install --save @redneckz/react-bem-helper
$ yarn add @redneckz/react-bem-helper

Motivation

This utility helps to declare BEM entities in terms of React components. Primarily it useful for projects with CSS artifacts (Sass, Less, PostCSS, ...).

Also compared to other libraries this one is aimed at simplicity and incremental adaptation of BEM (even for proprietary projects).

Features

  1. Configurable
  2. BEM mixins support
  3. Modular CSS support
  4. Flow definitions
  5. Very small bundle ~8Kb
  6. Almost no dependencies

Prerequisites

  1. BEM Methodology
  2. Higher-Order Components
  3. Flow
  4. classnames

Usage

.some-button
    padding: 8px

    &--major
        background: blue

    &--size
        &--small
            padding: 4px
        &--large
            padding: 16px
import React from 'react';
import { BEM } from '@redneckz/react-bem-helper';
import styles from './some-button.sass';

const someButton = BEM(styles);

export const SomeButton = someButton(({ className, disabled, children }) => (
    <button className={className} disabled={disabled}>
        {children}
    </button>
));
<React.Fragment>
    <SomeButton major>Major</SomeButton>
    <SomeButton size="small">Small</SomeButton>
    <SomeButton major size="large">
        Large
    </SomeButton>
    <SomeButton disabled>Disabled</SomeButton>
</React.Fragment>

will produce

<button class="some-button some-button--major">Major</button>
<button class="some-button some-button--size--small">Small</button>
<button class="some-button some-button--major some-button--size--large">Large</button>
<button class="some-button" disabled>Disabled</button>

Any valid component can be used to declare block or its elements

export const SomeButton = someButton(
    class extends React.PureComponent {
        render() {
            const { className, disabled, children } = this.props;
            return (
                <button className={className} disabled={disabled}>
                    {children}
                </button>
            );
        }
    },
);
export const SomeButton = someButton('button'); // DOM component

Also library provides several factory functions to declare DOM components with restricted attributes list (div, span, form, button, input, label, textarea)

import React from 'react';
import { BEM, div } from '@redneckz/react-bem-helper';
import styles from './some-button.sass';

const someButton = BEM(styles);

export const SomeButton = someButton(div({ role: 'button' }));

Block with elements

.panel
    display: flex

    &__item
        flex-grow: 0

        &--align
            &--start
                align-self: flex-start
            &--center
                align-self: center
            &--end
                align-self: flex-end

    &__spread
        flex-grow: 1
import React from 'react';
import { BEM, div } from '@redneckz/react-bem-helper';
import styles from './panel.sass';

const panel = BEM(styles);

export const Panel = panel('div');
export const PanelItem = panel.item(div());
export const PanelSpread = panel.spread('div');

Configuration

BEM naming convention

import React from 'react';
import { Config } from '@redneckz/react-bem-helper';

Config.ELEMENT_SEPARATOR = '__';
Config.MODIFIER_SEPARATOR = '--';

Flow

Generate stub for classnames

$ flow-typed create-stub classnames@x.x.x

Do not forget to configure includes and ignores to put library into scope.

License

MIT