@onenexus/cell

    1.0.0-beta.21 • Public • Published

    GitHub license Build Status npm version npm downloads

    Style BEM DOM elements using Sass [View SassDocs]

    CodeSandbox Demos
    Standard Demo JavaScript Demo React Demo Basic Sass-Only Demo

    Overview

    Cell is used for styling DOM elements that follow the Cell naming convention (which is almost identical to BEM).

    Learn how to integrate with React components

    Example

    Given the following markup for an accordion with an active panel component:

    View CodeSandbox Demo

    Unlike traditional BEM, you do not need separate classes for modifiers

    <div class="accordion">
      <div class="accordion__panel">
        <div class="accordion__title">foo</div>
        <div class="accordion__content">bar</div>
      </div>
      <div class="accordion__panel--active">
        <div class="accordion_title">fizz</div>
        <div class="accordion_content">buzz</div>
      </div>
    </div>

    This can be styled with Cell like so:

    @include module('accordion') {
      @include component('panel') {
        ...
     
        @include is('active') {
          @include component('content') {
            display: block;
          }
        }
      }
     
      @include component('title') {
        ...
      }
     
      @include component('content') {
        ...
        display: none;
      }
    }

    Using context()

    The above examples use the traditional cascading paradigm to apply styles under certain conditions. You can see that to show the content component above, the display property is applied in a cascading fashion inside the panel component.

    Cell allows you to go about this in a dfferent way, allowing you to keep all styles pertaining to a single component in one place, thanks to the context() mixin, as seen in this example (this will produce identical CSS to the previous example):

    @include module('accordion') {
      @include component('panel') {
        ...
      }
     
      @include component('title') {
        ...
      }
     
      @include component('content') {
        ...
        display: none;
     
        @include context(($this, 'panel'), 'active') {
          display: block;
        }
      }
    }

    Using Cell Atoms

    Learn more about Cell Atoms

    Continuing from the previous example, the display Atom can instead be used to handle the display property:

    @include module('accordion') {
      @include component('panel') {
        ...
      }
     
      @include component('title') {
        ...
      }
     
      @include component('content') {
        ...
        @include display((($this, 'panel'), 'active'), blocknone);
      }
    }

    Installation & Setup

    npm install --save @onenexus/cell
    
    // this path will vary depending on where the library is being imported 
    @import '../../node_modules/@onenexus/cell/dist/cell';

    If you are using Node Sass, you can import the library anywhere using:

    @import '~@onenexus/cell/dist/cell';

    See the JavaScript Configuration page for instructions on how to use JavaScript/JSON configuration

    Using with JavaScript

    Cell can be used with JavaScript for things like theming and module configuration.

    View CodeSandbox Demo

    Using React?

    Example

    modules/
    |--myModule/
    |  |--config.js
    |  |--styles.scss
    themes/
    |--myTheme.js
    app.scss
    
    themes/myTheme.js
    export default {
      colors: {
        primary: '#00d4ff',
        secondary: '#58ed02'
      },
      breakpoints: {
        small: '720px',
        large: '1400px'
      }
    }
    modules/myModule/config.js
    export default (theme) => ({
      name: 'myModule',
      background: theme.colors.primary,
      gutter: '1em'
    });
    modules/myModule/styles.scss
    @import 'config.js';
     
    @include module {
      display: block;
      margin-top: this('gutter');
     
      @media (min-width: theme('breakpoints', 'small')) {
        display: inline-block;
      }
    }
    app.scss
    @import '~@onenexus/cell/dist/cell';
    @import 'themes/myTheme.js';
    @import 'modules/myModule/styles';
    CSS Output
    .myModule[class*="myModule--"] {
      background: #00d4ff;
      display: block;
      margin-top: 1em;
    }
     
    @media (min-width: 720px) {
      .myModule[class*="myModule--"] {
        display: inline-block;
      }
    }

    Note that the background property is output to CSS despite not being hard-coded inside styles.scss - this is because configuration properties that correspond to CSS properties can be automatically parsed as CSS - read the Cell Query Draft page to learn more

    Read the JavaScript Configuration page for setup instructions and more information

    Using with React

    Using Cell with React can be as simple as configuring your Webpack to use Sass-Loader. See how the below React accordion component can be styled by importing its corresponding Cell module (styles.scss):

    View CodeSandbox Demo

    modules/Accordion/index.js
    import React, { useState } from 'react';
    import './styles.scss';
     
    const Accordion = ({ panels, ...props }) => {
      const [activeIndex, toggle] = useState(0);
     
      return (
        <div className='accordion' { ...props }>
          {panels.map(({ heading, content }, index) => (
            <div className={`accordion__panel${index === activeIndex ? '--active':''}`}>
              <div className='accordion__title' onClick={() => toggle(index)}>
                {title}
              </div>
     
              <div className='accordion__content'>
                {content}
              </div>
            </div>
          ))}
        </div>
      );
    }
     
    export default Accordion;

    Using with Lucid (React Library)

    Lucid is a React library for working with the Cell/BEM naming convention. If using Lucid, the above React component could be rewritten as:

    import React, { useState } from 'react';
    import { Module, Component } from '@onenexus/lucid';
    import './styles';
     
    const Accordion = ({ panels, ...props }) => {
      const [activeIndex, toggle] = useState(0);
     
      return (
        <Module name='accordion' { ...props }>
          {panels.map(({ heading, content }, index) => (
            <Component name='panel' active={index === activeIndex}>
              <Component name='heading' onClick={() => toggle(index)}>
                {heading}
              </Component>
     
              <Component name='content'>
                {content}
              </Component>
            </Component>
          ))}
        </Module>
      );
    }
     
    export default Accordion;

    This solution offers all the practical benefits of scoped styling (thanks to the underlying Cell/BEM naming convention) without any of the uglyness that BEM usually brings, and without any of the overhead that CSS-in-JS techniques (and actual scoping) bring, keeping everything clean and tidy.

    Useful Wiki Pages

    Mixins

    Cell comes with the following mixins to help create and structure your modules in the most efficient way possible:

    Utility Functions

    BEM Inspired Motivation

    The initial motiviation behind creating Cell is twofold:

    • Address the uglyness of BEM
    • Address the practical implementation of BEM using Sass

    BEM solves very real problems like no other solution due to its inherent nature, however it is often considered quite ugly; the __ and -- thrown into your HTML along with repeated keywords when using modifiers (block__component block__component--modifier-1 block__component--modifier-2) make the HTML extremely jarring to look at. Cell solves these issues by abstracting the logic into mixins and making use of CSS's wildcard attribute selector.

    Since the initial conception, Cell has evolved to become a fully-fledged framework for writing scalable and maintainable CSS.


    Install

    npm i @onenexus/cell

    DownloadsWeekly Downloads

    30

    Version

    1.0.0-beta.21

    License

    MIT

    Unpacked Size

    479 kB

    Total Files

    60

    Last publish

    Collaborators

    • avatar