Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/textkernel/bem
✨ Magically generates class names for React components
https://github.com/textkernel/bem
bem css-modules react
Last synced: about 1 month ago
JSON representation
✨ Magically generates class names for React components
- Host: GitHub
- URL: https://github.com/textkernel/bem
- Owner: textkernel
- License: mit
- Created: 2019-05-28T15:48:40.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-04T21:47:21.000Z (almost 2 years ago)
- Last Synced: 2024-10-12T09:29:54.509Z (about 1 month ago)
- Topics: bem, css-modules, react
- Language: TypeScript
- Homepage:
- Size: 2.28 MB
- Stars: 0
- Watchers: 6
- Forks: 1
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
[![Build Status](https://travis-ci.com/textkernel/bem.svg?branch=master)](https://travis-ci.com/textkernel/bem)
[![Coverage Status](https://coveralls.io/repos/github/textkernel/bem/badge.svg?branch=master)](https://coveralls.io/github/textkernel/bem?branch=master)
[![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/textkernel/bem.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/textkernel/bem/context:javascript)
![Package dependencies](https://img.shields.io/david/textkernel/bem.svg?style=flat)
![npm bundle size](https://img.shields.io/bundlephobia/minzip/@textkernel/bem.svg)
![Maintenance](https://img.shields.io/maintenance/yes/2019.svg)
[![npm version](https://img.shields.io/npm/v/@textkernel/bem.svg)](https://www.npmjs.com/package/@textkernel/bem)BEM
===![css modules + bem + react = love](https://raw.githubusercontent.com/textkernel/bem/master/docs/logo.svg?sanitize=true)
**Magically generates class names for React component.**
Installation
------------```sh
npm install @textkernel/bem --save
```
or
```sh
yarn add @textkernel/bem
```Usage
-----## 1. Create and export your own **bem** function using `make`.
```js
// initBem.jsimport make from 'bem';
// `make` allows you to customize bem prefixes
export default make({
elemPrefix: '__',
modPrefix: '--',
valuePrefix: '_',
});
```## 2. Import **bem** into a React component, create `block` and `elem` functions and use them in render method
```js
// Button.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import bem from './initBem';
import classnamesMap from './Button.scss';const { block, elem } = bem(
'Button', // Block name
classnamesMap // Class names dict generated by CSS modules loader
);const Button = (props) => (
{props.children}
{props.children}
);Button.propTypes = {
active: PropTypes.bool,
};Button.defaultProps = {
active: false,
};export default Button;
```### Passing custom class names to `block` and `elem` functions.
#### block
If `props` object that you pass to `block` contains `className` property, then this `className` is applied to the resulting class name list. In case of `elem` function though it is ignored.
```ts
const result = block('Button', { size: 'big', className: 'custom-class-name' });result.className === 'Button Button--size_big custom-class-name' // true
```#### elem
If `props` object that you pass to `elem` contains `elemClassName` property, then this `elemClassName` is applied to the resulting class name list. In case of `block` function though it is ignored.
```ts
const result = elem('label', { position: 'right', elemClassName: 'custom-elem-class-name' });result.className === 'Button__label Button__label--position_right custom-elem-class-name' // true
```## 3. Write css respecting BEM methodology and it will be automatically picked up.
```css
/* Button.scss *//* Component's root node class name */
.Button {display: inline-block;
/*
Block: "Button", modifier: "active" (based on props.active), value: true.
Is applied to the component's root node when props.active = true is set.
*/
&--active {
color: red;
}/*
Block: "Button", modifier: "type" (based on props.type), any truthy value.
Is applied to the component's root node when `props.type = "normal"` is set.
*/
&--type {
border: 1px;
}/*
Block: "Button", modifier: "type" (based on props.type), value: "normal".
Is applied to the component's root node when `props.type = "normal"` is set.
*/
&--type_normal {
background-color: grey;
}/*
Block "Button", modifier "type" (based on props.type), value "extraordinary".
Is applied to the component's root node when `props.type = "extraordinary"` is set.
*/
&--type_extraordinary {
background-color: red;
}/*
Block "Button", modifier "clicked" (based on state.clicked), value true.
Is applied to the component's root node when `state.clicked = true` is set.
*/
&--clicked {
border-style: dashed;
}/*
Block "Button", element "label"
Is applied to the component's label node.
*/
&__label {
color: blue;
}/*
Block "Button", element "label", modifier: "active" (based on props.active), value: true.
Is applied to the component's label node when props.active = true is set.
*/
&__label--active {
color: yellow;
}/*
Block "Button", element "label", modifier "extraordinary" (based on props.type), value "extraordinary".
Is applied to the component's label node when `props.type = "extraordinary"` is set.
*/
&__label--type_extraordinary {
color: orange;
}
}
```Examples of outcome
-------------------Having the example above we can get the following results.
`bem` decorator adds only classnames that are declared in a stylesheet and
respectively exists in classnames map.### No props:
```html↓ ↓ ↓
```
### Prop `active` is set:
```html
↓ ↓ ↓
```
### Prop `active` and `type` are set:
**Note** that property of a boolean type `active={true}` produces `Button__label--active` (*without* mod value), when property of a string type `type='extraordinary'` gives us two class names: `Button__label--type` (*without* mod value) and `Button__label--type_extraordinary` (*with* mod value).
```html
↓ ↓ ↓
```
### Prop `active` equals false
No classnames will be produced if boolean property has `false` value.
```html↓ ↓ ↓
```
### Clicked state
```html
↓ ↓ ↓
```