Created
November 23, 2017 03:16
-
-
Save gildniy/e328665cbd14d1c2b8d500d077a7222f to your computer and use it in GitHub Desktop.
Expressive BEM mixins (for BEM and namespacing) as reference to this post using the same approach for .sass file (https://codepen.io/andersschmidt/post/expressive-bem-with-sass-part-ii-a-first-draft-of-mixins)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ------------------------------------------------ | |
// Expressive BEM mixins (for BEM and namespacing) | |
//------------------------------------------------- | |
//--------------------------------------------- | |
// Creates a new, top-level Block | |
// -------------------------------------------- | |
// If a type (e.g. component, module, utility) | |
// is given, it will auto-generate a namespaced | |
// class that adheres to Harry Roberts' post | |
// on namespaced BEM classes. | |
// If given: @include new(product-item, component) | |
// Produces: .c-product-item | |
// Remember, the $type is optional. | |
@mixin new($name, $type: null) { | |
@at-root { | |
@if ($type != null) { | |
$namespace: str-slice($type, 0, 1); | |
.#{$namespace}-#{$name} { | |
@content | |
} | |
} @else { | |
.#{$name} { | |
@content | |
} | |
} | |
} | |
} | |
@mixin class($name, $type: null) { /* OOP class alias */ | |
@include new($name, $type: null) { | |
@content | |
} | |
} | |
@mixin createClass($name, $type: null) { /* React-inspired class alias */ | |
@include new($name, $type: null) { | |
@content | |
} | |
} | |
/*--------------------------------------------- | |
// Creates an Element | |
//---------------------------------------------*/ | |
// If given: | |
// @include new(product-item, component){ | |
// @include has(title) | |
// } | |
// | |
// Produces: | |
// .c-product-item {} | |
// .c-product-item__title {} | |
// | |
// If given: | |
// @include new(person){ | |
// @include when(female); | |
// @include has(hand, person) refers to the parent scope | |
// } | |
// } | |
// | |
// Produces: | |
// .person {}; | |
// .person--female {}; | |
// .person--female .person__hand {}; | |
// | |
@mixin has($name, $childOf: '') { | |
@if ($childOf != '') { | |
.#{$childOf}__#{$name} { | |
@content | |
} | |
} @else { | |
@at-root { | |
#{&}__#{$name} { | |
@content | |
} | |
} | |
} | |
} | |
//---------------------------------------------- | |
// Creates a Modifier | |
// --------------------------------------------- | |
// If given: | |
// @include new(person){ | |
// @include when(female) | |
// } | |
// | |
// Produces: | |
// .person {} | |
// .person--female {} | |
@mixin when($name) { | |
@at-root { | |
#{&}--#{$name} { | |
@content | |
} | |
} | |
} | |
//----------------------------------------------- | |
// Creates a behaviorial State | |
// ----------------------------------------- | |
// If given: | |
// @include new(menu, component){ | |
// @include has(item){ | |
// @include if(active) | |
// } | |
// } | |
// | |
// Produces: | |
// .c-menu {} | |
// .c-menu__item {} | |
// .c-menu__item.is-active {} | |
@mixin if-its($state) { | |
&.is-#{$state} { | |
@content | |
} | |
} | |
@mixin if($state) { | |
@include if-its($state) { | |
@content | |
} | |
} | |
//----------------------------------------------- | |
// Creates an ownership State | |
//----------------------------------------------- | |
// If given: | |
// @include new(menu, component){ | |
// @include has(item){ | |
// @include with(dropdown) | |
// } | |
// } | |
// | |
// Produces: | |
// .c-menu {} | |
// .c-menu__item {} | |
// .c-menu__item.has-dropdown {} | |
@mixin got($something) { | |
&.has-#{$something} { | |
@content | |
} | |
} | |
@mixin with($something) { | |
@include got($something) { | |
@content | |
} | |
} | |
//----------------------------------------------- | |
// Allows importing Blocks into other Blocks | |
//----------------------------------------------- | |
// Uses @extend, so BEWARE. This is experimental, | |
// may mess up your code, so double-check that the | |
// output is what you want. | |
// | |
// This potentially allows you to create blocks | |
//(components, modules etc.) seperately and instead | |
// load them into a parent block / component similar | |
// to something like React. | |
// | |
// As a silly example, let's say you've made | |
// a List component and your Product | |
// component should be imported into, rather than | |
// nested as a @include has: | |
// | |
// @include new(product, component){ | |
// color: red; | |
// height: 50px; | |
// width: 100px; | |
// } | |
// | |
// @include new(list, component){ | |
// display: block; | |
// margin: 0; | |
// | |
// @include import(c-product) | |
// } | |
// | |
// Note that we're using the generated class name | |
// as the parameter value in @include import. So just saying | |
// @include import(product) won't work(unless you wrote | |
// @include new(product) without setting a type). | |
@mixin import($something) { | |
@at-root { | |
& .#{$something} { | |
@extend .#{$something}; | |
@content | |
} | |
} | |
} | |
@mixin fetch($something) { | |
@include import($something) { | |
@content | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment