sasslessscss-mixinsmetro-ui-css

Converting LESS "when" statements into SCSS conditional statements


To cite my sources, I'm converting the tiles functionality from Metro-UI into a custom SCSS/Angular project I'm building. So far I've been able to convert much of it 1:1 by watching for mixins, includes, and variables. However, I'm not following what Metro's team is doing in this section when it comes to column arrangement. Their original code (from their LESS file - line 243):

.tiles-grid {
    .create-tiles-cells(@i: 1, @k: 1) when (@k <= @i) {

        .tile-small.col-@{k} {
            grid-column: @k / span 1;
        }

        .tile-medium.col-@{k} {
            grid-column: @k / span 2;
        }

        .tile-wide.col-@{k} {
            grid-column: @k / span 4;
        }

        .tile-large.col-@{k} {
            grid-column: @k / span 4;
        }

        .tile-small.row-@{k} {
            grid-row: @k / span 1;
        }

        .tile-medium.row-@{k} {
            grid-row: @k / span 2;
        }

        .tile-wide.row-@{k} {
            grid-row: @k / span 4;
        }

        .tile-large.row-@{k} {
            grid-row: @k / span 4;
        }


        //.col-@{k} {
        //    grid-column: @k;
        //}
        //.row-@{k} {
        //    grid-row: @k;
        //}
        .create-tiles-cells(@i; @k + 1);
    }
    .create-tiles-cells(12);
}

.tiles-grid {
    &.size-half {
        width: 70px + @tileMargin * 2;
    }

    .create-tiles-grid-size(@i: 1, @k: 1) when (@k <= @i) {
        &.size-@{k} {
            width: (@tileCellSize + @tileMargin * 2) * @k;
        }

        .create-tiles-grid-size(@i; @k + 1);
    }
    .create-tiles-grid-size(10);
}

.tiles-grid {

    .generate-tiles-media-options(@mediaBreakpointListMobileLength);
    .generate-tiles-media-options(@name, @j: 1) when (@j <= @mediaBreakpointListMobileLength) {
        @m: extract(@mediaBreakpointListMobile, @j);

        @media screen and (min-width: @@m) {
            .create-tiles-cells(@i: 1, @k: 1) when (@k <= @i) {
                .col-@{m}-@{k} {
                    grid-column: @k;
                }
                .row-@{m}-@{k} {
                    grid-row: @k;
                }
                .create-tiles-cells(@i; @k + 1);
            }
            .create-tiles-cells(12);

            .create-tiles-grid-size(@i: 1, @k: 1) when (@k <= @i) {
                &.size-@{m}-half {
                    width: 70px + @tileMargin * 2;
                }
                &.size-@{m}-@{k} {
                    width: (@tileCellSize + @tileMargin * 2) * @k;
                }

                .create-tiles-grid-size(@i; @k + 1);
            }
            .create-tiles-grid-size(10);
        }

        .generate-tiles-media-options(@name, @j + 1);
    }
}

My conversion so far:

.tiles-grid {
    @mixin create-tiles-cells($i: 1, $k: 1) when ($k <= $i){

        .tile-small.col-#{$k} {
            grid-column: $k / span 1;
        }

        .tile-medium.col-#{$k} {
            grid-column: $k / span 2;
        }

        .tile-wide.col-#{$k} {
            grid-column: $k / span 4;
        }

        .tile-large.col-#{$k} {
            grid-column: $k / span 4;
        }

        .tile-small.row-#{$k} {
            grid-row: $k / span 1;
        }

        .tile-medium.row-#{$k} {
            grid-row: $k / span 2;
        }

        .tile-wide.row-#{$k} {
            grid-row: $k / span 4;
        }

        .tile-large.row-#{$k} {
            grid-row: $k / span 4;
        }


        //.col-${k} {
        //    grid-column: $k;
        //}
        //.row-${k} {
        //    grid-row: $k;
        //}
        @include create-tiles-cells($i, $k + 1);
    }
    @include create-tiles-cells(12);
}

.tiles-grid {
    &.size-half {
        width: 70px + $tileMargin * 2;
    }

    @mixin create-tiles-grid-size($i: 1, $k: 1) when ($k <= $i){
        &.size-#{$k} {
            width: ($tileCellSize + $tileMargin * 2) * $k;
        }

        @include create-tiles-grid-size($i, $k + 1);
    }
    @include create-tiles-grid-size(10);
}

.tiles-grid {

    @include generate-tiles-media-options($mediaBreakpointListMobileLength);
    @mixin generate-tiles-media-options($name, $j: 1) when ($j <= $mediaBreakpointListMobileLength){
        $m: extract($mediaBreakpointListMobile, $j);

        @media screen and (min-width: $m) {
            @mixin create-tiles-cells($i: 1, $k: 1) when ($k <= $i){
                .col-#{$m}-#{$k} {
                    grid-column: $k;
                }
                .row-#{$m}-#{$k} {
                    grid-row: $k;
                }
                @include create-tiles-cells($i, $k + 1);
            }
            @include create-tiles-cells(12);

            @mixin create-tiles-grid-size($i: 1, $k: 1) when ($k <= $i){
                &.size-#{$m}-half {
                    width: 70px + $tileMargin * 2;
                }
                &.size-#{$m}-#{$k} {
                    width: ($tileCellSize + $tileMargin * 2) * $k;
                }

                @include create-tiles-grid-size($i, $k + 1);
            }
            @include create-tiles-grid-size(10);
        }

        @include generate-tiles-media-options($name, $j + 1);
    }
}

It's of course the "when" statement that is causing the issue. I understand from similar questions that I may need to use a "for" or "each" statement and break it down from there, but the syntax rules are very different logic when I'm reviewing similar answers (like this one). Since I didn't author the original LESS syntax I'm trying to work backwards through their logic to determine its SCSS equivalent.

From what I can tell it's trying to determine how to spread out the grids if/when the two values for I and K are different, but since you can't create a new class based upon a conditional variable in SCSS I'm getting tripped up. I'd appreciate any guidance. This is the last portion of my code that won't compile.


Solution

  • LESS and SCSS are a bit different when it comes to syntax – I always found SCSS to be the better choice – why my knowledge on LESS is somewhat limited.

    I ran the LESS code on codepen and looked at the output – I think I'm able to help you with the first two parts. The last part with the media queries makes no sense it just produces a bunch of media queries and classes doing the same thing as the size part... (let me know if you can produce something meaningful - then I'll have a second look).

    I hope the comments makes sense :-)

    Code on sassmeister.com

    // -------------------------------------------------------
    //  Create tile cells mixin
    //  if no arguments are passed 12 will be used as default
    //  small note! mixins can't be nested in selectors
    // -------------------------------------------------------
    @mixin create-tiles-cells($count: 12){
      //  map holding size information (think object like)
      $sizes:(small: 1, medium: 2, wide: 3, large: 4);
    
      //  outer selector 
      .tiles-grid {
        //  loop from 1 through cell count
        @for $i from 1 through $count {
          //  loop through sizes map
          @each $key, $value in $sizes {
            //  print class using $key (small, medium,...)
            .tile-#{$key} {
              //  use & to bind the .col and .row class to the parent .tile-xxx  
              &.col-#{$i} { grid-column: $i / span $value; }
              &.row-#{$i} { grid-row:    $i / span $value; }
            }
          }
        }  
      }
    }
    
    
    // -------------------------------------------------------
    //  Create tile sizes mixin
    //  if no arguments are passed 10 will be used as default
    // -------------------------------------------------------
    @mixin create-tiles-grid-size($count: 10){
      //  variables 
      $tile-margin: 5px;
      $tile-cell-size: 150px;
    
      // @tileMargin: 5px;
      .tiles-grid {  
        //  hardcoded half class 
        &.size-half { width: 70px + $tile-margin * 2;}
        //  loop from 1 through size count
        @for $i from 1 through $count {
          &.size-#{$i}{ 
            width: ($tile-cell-size + $tile-margin * 2) * $i; 
          }
        }
      }
    }
    
    
    // -------------------------------------------------------
    // Include the mixins 
    // -------------------------------------------------------
    @include create-tiles-cells(12);
    @include create-tiles-grid-size(10);