whizark
10/14/2014 - 12:11 AM

Sass: Creating Custom Scope & Scope-based Default Value #sass

Sass: Creating Custom Scope & Scope-based Default Value #sass

// ----
// Sass (v3.4.5)
// Compass (v1.0.1)
// ----

// Sass: Creating custom scope & scope-based default value in Sass
//
// A use case using mixin.
// This is pseudo code so you need implement some code.
//
// Other ideas: https://github.com/whizark/xass#ideas

// --------------------------------------------------------------------------------
// The FILO stack to keep scope & the property values
$-scope: (
  //  <scope-id>: (
  //    <name>: <value>,
  //    ...
  // ),
  // ...
);

// Setter function
@function set($name, $value) {
  // 1. Get the $-scope value by current scope ID
  // 2. Set the $value to the $name property in the current scope
  // 3. Merge back the value(1) to $-scope

  @return $value;
}

// Getter function
@function get($name, $default: null) {
  $value: null;

  // 1. Get the $-scope value by current scope ID
  // 2. Get the value of $name property
  // 3. (Returns $default value,
  //     if the $name doesn't exist in the current scope.
  //     Or follow the scope-chain.)

  @return $value;
}

// The mixin to create new scope
@mixin scope() {
  // 1. Create a new scope ID
  // 2. Push the scope ID and empty Map into $-scope

  // 3. Do something
  // e.g. call constructor function by using call()
  //      or set default values       etc.

  @content;

  // 4. Pop the current scope ID and Map(2) from $-scope
}

// --------------------------------------------------------------------------------
// Use case
// Component Definition
@mixin button(
  $font-size  : get('font-size', 16px),  // THE SCOPE-BASED DEFAULT VALUES.
  $color      : get('color', #00f),      // The current scope value is used,
  $line-height: get('line-height', 1.4)  // if an argument is omitted.
) {
  // Computes the vertical padding based on font-size & line-height.
  $padding          : 16px;
  $line-height-px   : ($font-size * $line-height);
  $line-height-space: ($line-height-px - $font-size) / 2;
  $vertical-padding : $padding - $line-height-space;

  // Declarations
  display    : inline-block;
  font-size  : $font-size;
  padding    : $vertical-padding $padding;
  background : $color;
  line-height: $line-height;
}

@mixin another-mixin(   // This mixin only accept $color,
  $color: get('color', #f0f)  // but you can pull the value from the current scope.
) {
  color: $color;
}

// Actual Usage
// 1. Create new scope.
@include scope() {
  // SCOPE BEGIN
  // THE SCOPE CAN BE NESTED.
    
  // 2. Set Property
  $font-size  : set('font-size'  , 13px);  // The base font-size;
  $color      : set('color'      , #f00);  // The base(primary) color;
  $line-height: set('line-height', 1.6);   // The base line-height;

  // 3. Call method(s)/mixin(s)
  //    You don't have to pass arguments.
  .button {
    @include button();
  }

  .another-mixin {
    @include another-mixin();
  }

  // @include other-mixins(); with/WITHOUT arguments.
  // ...

  // SCOPE END
  // The current scope values are popped.
}