# BEM and Coding Standards

## Watch videos

Style (SCSS) best-practices:

{% embed url="<https://youtu.be/W4LUYfLUCqs>" %}

Scripting (React) best-practices:

{% embed url="<https://youtu.be/0tSXwEg26UA>" %}

## BEM

This project uses [BEM](https://en.bem.info/methodology/) (Block Element Modifier) approach to organize styles.

Following rules are true specifically in ScandiPWA project case:

* Blocks and elements start with uppercase: `Header`
* If block or element has 2 or more words in its name - they both start with uppercase: `MenuItem`
* Blocks and elements are divided with minus sign (`-`): `Header-MenuItem`
* Mods are divided with an underscore (`_`): `Header-MenuItem_visible`
* Mods start with lowercase
* Mods may consist of:
  * a key and a value: `MenuItem_type_dropdown` or `MenuItem_type_defaultLocal` if modifier has 2 or more words in its key or value.
  * a key without value included in the name: `MenuItem_visible`
* For boolean modifiers, the value is not included in the name: `MenuItem_visible`
* If mod has 2 or more words in its name - it is written as follows: `backgroundColor_red`
* Block’s element can’t be accessed from outside the block

## How to use it in Javascript?

This projects uses [rebem-jsx-plugin](https://github.com/rebem/rebem-jsx) to implement BEM in this project.

{% hint style="danger" %}
**Note**:

usage of `className` prop is prohibited
{% endhint %}

### **Defining a block**

```markup
<div block="Header">

// Results into
<div className="Header">
```

### **Defining an element of a block**

```markup
<div block="Header" elem="Message">

// Results into
<div className="Header-Message">
```

### **Defining a block which is an element of parent block**

{% hint style="warning" %}
**Note:**

string props are declared with double quotes (`"`), while the object keys are declared with single quotes (`'`).
{% endhint %}

```markup
<div block="Menu" mix={ { block: 'Header', elem: 'Menu' }}>

// Results into
<div className="Menu Header-Menu">
```

### **Using mods (modificators) prop**

* Boolean modifier

{% hint style="warning" %}
**Note:**

the prop name should start with `is` to immediately represent boolean
{% endhint %}

```markup
<div block="Menu" mods={ { isVisible: true } }>

// Results into
<div className="Menu Menu_isVisible">
```

* Single key-value modifier

```markup
<div block="Menu" mods={ { type: 'horizontal' } }>

// Results into
<div className="Menu Menu_type_horizontal">
```

* Multiple key -> value modifier

```markup
<div block="Menu" mods={ { type: 'horizontal', behavior: 'autoClose' } }>

// Results into
<div className="Menu Menu_type_horizontal Menu_behavior_autoClose">
```

## How to use it in styles (SCSS)?

Let’s consider following JSX snippet:

```jsx
<form class="Form Form_state_error">
    <div class="Field Form-Field">
        <span class="Field-Message">Error</span>
        <input class="Field-Input" name="default" placeholder="Please enter a value">
    </div>
</form>
```

* How to access block:

```css
.Form {
    background-color: red;
}
```

* How to access block’s element:

{% hint style="warning" %}
**Note:**

`&` stands for parent selector, it is very useful in order to not repeat yourself.
{% endhint %}

```css
.Form {
    &-Field {
        background-color: blue;
    }
}
```

* How to access modified block’s element:

```css
.Form {
    &_state {
        &_error {
            .Field-Message {
                background-color: red;
            }
        }

        &_warning{
            .Field-Message {
                background-color: yellow;
            }
        }
    }
}
```

## Coding standard: description of ESLint rules

### `file-structure`

File structure must comply to the following guidelines:

* File structure must be flat, meaning that nesting components inside of other components is prohibited.
* Extending root directory `src` with custom folders is prohibited.
* File structure regulations imply having files with certain postfixes for certain functionality parts. Allowed postfixes for directories are the following
  * Component and route: `.component` `.container` `.style` `.config` `.unstated`
  * Store: `.action` `.dispatcher` `.reducer`
  * Query: `.query`
  * Style, type: **none**
* For files which are in their own directories with functionality related only to them (e.g routes, components), names should match the name of the directory these files are in.

### **`derived-class-names`**

Class name must match name of the file it is inside of. Expected class names for all the files *other* than components are `name + prefix` (e.g. class inside of **AddToCart.container**.js file must be called **AddToCartContainer** and not otherwise).

Examples of **incorrect** code for this rule:

```javascript
// in MyComponent.container.js
class Abc { /** ... */ }

// in Hello.component.js
class HelloComponent { /** ... */ }
```

Examples of **correct** code for this rule:

```javascript
// in MyComponent.container.js
class MyComponentContainer { /** ... */ }

// in Hello.component.js
class Hello { /** ... */ }
```

### `use-extensible-base`

All components should be extensible. For class to be extensible it should be derived from extensible base. Replacements of non-extensible bases are the following and should not be imported - these are available in any point of the application.

* `PureComponent` -> `ExtensiblePureComponent`
* `Component` -> `ExtensibleComponent`
* *`no base`* -> `ExtensibleClass`

The `ExtensiblePureComponent`, `ExtensibleComponent` and `ExtensibleClass` requires no import.

Examples of **incorrect** code for this rule:

```javascript
import { PureComponent } from 'react';
class A extends PureComponent { /** ... */ }
```

Examples of **correct** code for this rule:

```javascript
// notice, no import, it is a global variable
class A extends ExtensiblePureComponent { /** ... */ }
```

### `only-one-class`

There should be only one class per file. Multiple classes inside of one file are not allowed.

Examples of **incorrect** code for this rule:

```javascript
// A.component.js
class A {
    /** ... */
}

class B {
    /** ... */
}
```

Examples of **correct** code for this rule:

```javascript
// A.component.js
class A {
    /** ... */
}
```

### `no-non-extensible-components`

Non-extensible components are not allowed. Use extensible bases instead of regular `Component` or `PureComponent`.

Examples of **incorrect** code for this rule:

```javascript
class A extends PureComponent {
    /** ... */
}
```

Examples of **correct** code for this rule:

```javascript
class A extends ExtensiblePureComponent{
    /** ... */
}
```

### `export-level-one`

Variables and classes if declared on root level must be exported (and not by default!)

Examples of **incorrect** code for this rule:

```javascript
const SOME_IMPORTANT_NUMBER = 777;

class A extends ExtensiblePureComponent {
    /** ... */
}
```

Examples of **correct** code for this rule:

```javascript
export const SOME_IMPORTANT_NUMBER = 777;

export class A extends ExtensiblePureComponent{
    /** ... */
}
```

### `use-middleware`

Wrap default export classes in `middleware` function in order to make classes extensible and assign namespaces to them.

Examples of **incorrect** code for this rule:

```javascript
// Component/A/A.component.js
export default A;
// Route/B/B.container.js
export default connect(mapStateToProps, mapDispatchToProps)(BContainer)
```

Examples of **correct** code for this rule:

```javascript
// Component/A/A.component.js
export default middleware('Component/A/Component', A);
// Route/B/B.container.js
export default middleware('Route/B/Container', BContainer);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://scandipwa.gitbook.io/docs/how-to-tutorials-intermediate/bem-and-coding-standards.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
