npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

postcss-system

v0.0.5

Published

Author your CSS with a BEM-compliant component-oriented system.

Downloads

4

Readme

Build Status NPM version Dependency Status devDependency Status Coverage Status

system

please note, this module is in its early development phase and will likely change frequently.

system is a PostCSS plugin developed at io that allows you to augment your CSS with a syntax that aids in creating BEM-compliant front-end components and reads like a class definition.

system essentially transforms this...

component(tweet) has(profile) {
  border: 1px solid #eee;
}
component(tweet) when(featured) has(profile) {
  border-color: yellow;
}

...into this:

.tweet--profile {
  border: 1px solid #eee;
}
.tweet.\+featured .tweet--profile {
  border-color: yellow;
}

Combined with postcss-nested (which is loaded before system), the syntax looks something like this:

component(tweet) {
  has(profile) {
    border: 1px solid #eee;
  }
  when(featured) {
    has(profile) {
      border-color: yellow;
    }
  }
}

For more features, check out the API.

Inspiration & Credit

This is inspired by, and very similar to another library called CSStyle by Dave Geddes.

Further inspiration comes from wanting to use BEM without sacrificing the power of the cascade, which BEM supplements, rather than augments. Following the system syntax will ensure that you never have to worry about using !important or loading your components in any specific order, as long as your top-most document element (e.g. body) has an id attribute of system.

Why re-invent the wheel? We needed a completely customisable version of CSStyle that could be used from any preprocessor and shares a single code base, because some of our developers have varying toolsets, and we also have ideas that will eventually deviate system from being too similar to CSStyle. Right now, system already supports multiple arguments, two extra methods (container for setting styles directly on a container, and is for setting element state), the ability to output mixins for all 3 major preprocessors that transform to the required PostCSS syntax and is so customizable you can even change the API.

Installation

system can be installed with npm, which comes pre-installed with Node.js

$ npm install postcss-system --save-dev

Usage

system is supported anywhere PostCSS is supported. This means you can use it from Gulp, Grunt, plain JavaScript, etc.

var postcss = require('postcss');
var system = require('postcss-system');
var nested = require('postcss-nested');

postcss([nested, system.postcss/*([options={}])*/]);

JavaScript API

system.postcss([settings:Object])

This method registers system as a PostCSS plugin, and is responsible for transforming your CSS. Typically, you would pass this method to your PostCSS plugin pipeline, after postcss-nested (that is, if you're using postcss-nested), either as a plain function reference (system.postcss) or a function call (system.postcss()).

It accepts an optional settings object. For more info, check out Options.

Example:

postcss([system.postcss({root: '#root'})]);

system.mixins(settings:Object)

This method accepts a compulsory settings object, this is the same object one might pass to system.postcss, however settings.preprocessor.output and settings.preprocessor.engine are required in order for this to work. Check out Options for more details.

Given the correct details, it will output a mixins file for your chosen CSS preprocessor engine to the output path, that you can then @import and use to compile down to PostCSS syntax. This method is only useful if you have a CSS build task that involves piping preprocessor output to PostCSS.

Be sure to call this before system.postcss. Any settings passed to this method will be inherited by system.postcss.

It also returns a promise.

Example:

system.mixins({
  preprocessor: {
    engine: 'stylus',
    output: path.join(__dirname, 'assets', 'styles')
  }
});

Then, at the top of your main Stylus file:

@import 'system'

This works for sass, scss and less too.

Options

Here are the default options for system:

{
      preprocessor: {
        output    : '.', // the output path for the system mixins file
        engine    : null, // what css preprocessor you're using
        namespace : '', // a namespace to prepend to each method
        filename  : 'system' // the name of the mixins file
      },
      root: '#system', // the ID attribute for the root node
      mixins: { // yes, you can customise the names of each method
        block    : 'component',
        element  : 'has',
        modifier : 'when',
        state    : 'is',
        context  : 'inside',
        util     : 'util',
        parent   : 'container'
      },
      prefixes: { // and choose your own prefixes
        block    : '.',
        element  : '--',
        modifier : '.\\+',
        state    : ':',
        context  : '.\\@',
        util     : '.\\~',
        parent   : '.\\@'
      },
      suffixes: { // and suffixes
        block    : '',
        element  : '',
        modifier : '',
        state    : '',
        context  : '',
        util     : '',
        parent   : ''
      },
      extensions: { // what file extension to use for your mixins file
        sass   : 'sass',
        scss   : 'scss',
        stylus : 'styl',
        less   : 'less'
      },
      protectedStates: [ // these are not transformed by the `state` method
        'enabled',
        'disabled',
        'checked',
        'required',
        'visited'
      ]
    }

System API

component(args...)

Creates a component.

component(tweet) {
  color: blue;
}
.tweet {
  color: blue
}
<div class="tweet">...</div>

has(args...)

A component block has an element. An element sometimes also has an element.

component(tweet) {
  has(avatar) {
    border-radius: 50%;
    has(edit-icon) {
      background: url('wrench.png');
    }
  }
}
.tweet--avatar {
  border-radius: 50%;
}
.tweet--avatar--edit-icon {
  background: url('wrench.png');
}
<div class="tweet">
  <div class="tweet--avatar">
    <i class="tweet--avatar--edit-icon" />
  </div>
</div>

when(args...)

when a block or element is modified, it's styles are overriden. An element can also react to it's parent block's modifier.

component(tweet) {
  color: blue;
  when(featured) {
    color: yellow;
    has(avatar) {
      border: 1px solid yellow;
    }
  }
  has(avatar) {
    border-radius: 0;
    when(circular) {
      border-radius: 50%;
    }
  }
}
.tweet {
  color: blue;
}
.tweet.\+featured {
  color: yellow;
}
.tweet.\+featured .tweet--avatar {
  border: 1px solid yellow;
}
.tweet--avatar {
  border-radius: 0;
}
.tweet--avatar.\+circular {
  border-radius: 50%;
}
<div class="+featured tweet">
  <div class="+circular tweet--avatar">...</div>
</div>

is(args...)

When a component, container, or element is in a particular state, it receives new styles.

component(tweet) {
  is(hovered, focused) {
    transform: scale(1.1);
  }
  has(avatar) {
    is(visited) {
      opacity: 0.8;
    }
  }
}
container(testimonials) {
  is(hovered) {
    background: purple;
  }
}
.tweet:hover,
.tweet:focus {
  transform: scale(1.1);
}
.tweet--avatar:visited {
  opacity: 0.8;
}
.\@testimonials:hover {
  background: purple;
}

container(args...)

Creates a parent. This is useful if you follow the OOCSS principle of separating content from container.

container(about-us) {
  background: blue;
}
.\@about-us {
  background: blue;
}
<div class="@about-us">...</div>

inside(args...)

If a component is inside a container, you might choose to override specific properties.

component(tweet) {
  background: white;
  inside(testimonials) {
    background: transparent;
    color: #fff;
  }
}
.tweet {
  background: white;
}
#system .\@testimonials .tweet {
  background: transparent;
  color: #fff;
}
<div class="@testimonials">
  <div class="tweet"></div>
</div>

util(args...)

Creates a utility. These are generic and pretty specific - they will override everything with the exception of a component that is inside a container.

util(mt-10) {
  margin-top: 10px;
}
.\~mt-10 {
  margin-top: 10px;
}
<div class="tweet ~mt-10">...</div>

Mixins API

All mixins follow the same method signature.

Please Note that these mixins will only compile down to the syntax that is transformed by system through PostCSS, they are not to be used as standalone alternatives.

Stylus

+component(tweet, box)
  color: blue

SCSS

@include component(tweet, box) {
  color: blue;
}

SASS

+component(tweet, box)
  color: blue

LESS

.component('tweet, box', {
  color: blue;
});