ScandiPWA (deprecated)
User ManualGitHubSlack
  • ScandiPWA (deprecated)
  • React & PWA for dummies
    • Setting Up Environment and Talking Theory
    • Learning React Hands-on
    • Styling It
    • Learning ScandiPWA Way
  • START & UPGRADE
    • Linux Docker setup
    • Mac Docker setup
    • Setting up the theme with remote M2 server
    • Theme Upgrade to the latest version
    • Automated setup (BETA)
  • A TO Z OVERVIEW
    • Motivation
    • Challenges
    • File structure and UI components
    • Rewriting and Extending A Theme
  • DESCRIPTION OF CONTAINERS
    • Ngrok
  • FAQ
    • Development
    • Installation
    • Billing and license
    • Product support
    • What is PWA?
  • HOW-TO TUTORIALS - INTRODUCTORY
    • Base template
    • Connecting to the GraphQL resolver
    • Extension mechanism
    • Creating GraphQL resolver
    • Debugging and Inspecting
    • Setting Up Frontend
    • File Structure
    • Data Flow
    • Technology Stack
    • Changing environment
    • Theme Build and Configuration
    • Implementing Caching for New Caching Identities
    • Implementing a parent theme
  • HOW-TO TUTORIALS - INTERMEDIATE
    • Debugging in Chrome
    • Configuring XDebug
    • CLI in Docker
    • Postman & GraphQL Playground
    • VSCode Extensions
    • Plugins: implementing
    • Plugins: using and publishing
    • ESlint & StyleLint
    • How To Contribute
    • Migrating to a Newer Version
    • Installation on Existing Magento 2 Sever
    • BEM and Coding Standards
    • Tools of ScandiPWA
    • React Best Practices
  • FAQ
    • Untitled
Powered by GitBook
On this page
  • Watch videos
  • BEM
  • How to use it in Javascript?
  • Defining a block
  • Defining an element of a block
  • Defining a block which is an element of parent block
  • Using mods (modificators) prop
  • How to use it in styles (SCSS)?
  • Coding standard: description of ESLint rules
  • file-structure
  • derived-class-names
  • use-extensible-base
  • only-one-class
  • no-non-extensible-components
  • export-level-one
  • use-middleware
  1. HOW-TO TUTORIALS - INTERMEDIATE

BEM and Coding Standards

PreviousInstallation on Existing Magento 2 SeverNextTools of ScandiPWA

Last updated 4 years ago

Watch videos

Style (SCSS) best-practices:

Scripting (React) best-practices:

BEM

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?

Note:

usage of className prop is prohibited

Defining a block

<div block="Header">

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

Defining an element of a block

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

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

Defining a block which is an element of parent block

Note:

string props are declared with double quotes ("), while the object keys are declared with single quotes (').

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

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

Using mods (modificators) prop

  • Boolean modifier

Note:

the prop name should start with is to immediately represent boolean

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

// Results into
<div className="Menu Menu_isVisible">
  • Single key-value modifier

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

// Results into
<div className="Menu Menu_type_horizontal">
  • Multiple key -> value modifier

<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:

<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:

.Form {
    background-color: red;
}
  • How to access block’s element:

Note:

& stands for parent selector, it is very useful in order to not repeat yourself.

.Form {
    &-Field {
        background-color: blue;
    }
}
  • How to access modified block’s element:

.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:

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

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

Examples of correct code for this rule:

// 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:

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

Examples of correct code for this rule:

// 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:

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

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

Examples of correct code for this rule:

// 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:

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

Examples of correct code for this rule:

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:

const SOME_IMPORTANT_NUMBER = 777;

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

Examples of correct code for this rule:

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:

// 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:

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

This project uses (Block Element Modifier) approach to organize styles.

This projects uses to implement BEM in this project.

BEM
rebem-jsx-plugin