Skip to content

Commit

Permalink
Merge pull request #5 from IgniteUI/simeonoff/elevations
Browse files Browse the repository at this point in the history
feat(elevations): add functions and mixins
  • Loading branch information
simeonoff authored Jul 22, 2022
2 parents 50cb0e7 + 8368fbe commit 8eb07f5
Show file tree
Hide file tree
Showing 9 changed files with 244 additions and 0 deletions.
1 change: 1 addition & 0 deletions _index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@forward './sass/color';
@forward './sass/typography';
@forward './sass/elevations';
@forward './sass/utils';
1 change: 1 addition & 0 deletions sass/_index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@forward 'color';
@forward 'elevations';
@forward 'typography';
@forward 'utils';
87 changes: 87 additions & 0 deletions sass/elevations/_functions.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
@use 'sass:meta';
@use 'sass:map';
@use 'sass:list';

////
/// @group elevations
////

$factor: var(--ig-elevation-factor, 1);

/// Checks if the passed argument is a valid box-shadow.
/// @access public
/// @param {List} $shadow - A list of shadow properties.
/// @return {Boolean} - Returns a boolean depending on if the passed argument is a valid shadow.
@function _is-shadow($shadow) {
$lastIndex: list.length($shadow);

@if type-of($shadow) != list {
@return false;
}

@if $lastIndex < 2 or $lastIndex > 5 {
@return false;
}

@if list.separator($shadow) != space {
@return false;
}

@return true;
}

/// Transforms the passed box-shadow list according to the elevation factor value.
/// @access public
/// @param {List} $shadow - A list of shadow properties.
/// @return {List} - The transformed shadow list.
@function _transform-shadow($shadow) {
$result: ();

@each $value in $shadow {
@if meta.type-of($value) != color and $value != 0 and $value != inset {
$result: list.append($result, calc($factor * $value));
} @else {
$result: list.append($result, $value);
}
}

@return $result;
}

/// Sorts out a list of valid only box-shadows.
/// @access public
/// @param {List} $shadows - A list of shadow values.
/// @return {List} - The transformed shadow list.
/// @requires {function} _is-shadow
/// @requires {function} _transform-shadow
@function box-shadow($shadows) {
$result: ();
$s: ();

@if meta.type-of($shadows) != list {
@error 'shadow expects a list of box-shadow values. ex.: shadow((0 2px 2px black))';
}

@if list.separator($shadows) == space {
$s: list.append($s, $shadows);
}

@if list.separator($shadows) == comma {
$s: $shadows;
}

@each $shadow in $s {
@if _is-shadow($shadow) {
$result: list.append($result, _transform-shadow($shadow), $separator: comma);
}
}

@return $result;
}

/// Gets a CSS elevation variable by name.
/// @access public
/// @param {String} $name - The name of the shadow.
@function elevation($name) {
@return var(--ig-elevation-#{$name});
}
2 changes: 2 additions & 0 deletions sass/elevations/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@forward 'functions';
@forward 'mixins';
34 changes: 34 additions & 0 deletions sass/elevations/_mixins.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
@use '../utils' as *;

////
/// @group elevations
////

/// Generates CSS variables for a given elevations map.
/// @access public
/// @param {Map} $elevations - The elevations map to use to generate CSS variables.
///
/// @example scss Generate CSS variables for elevations.
/// $elevations: (
/// small: box-shadow(0 .125rem .25rem rgba(0 0 0 / 75%)),
/// medium: box-shadow(0 .25rem .5rem rgba(0 0 0 / 85%)),
/// large: box-shadow(0 .75rem 1rem rgba(0 0 0 / 95%)),
/// );
/// @include elevations($elevations);
///
@mixin elevations($elevations) {
$scope: if(is-root(), ':root', '&');

#{$scope} {
@each $level, $shadow in $elevations {
--ig-elevation-#{$level}: #{$shadow};
}
}
}

/// Includes box-shadow styles for an elevation by name
/// @access public
/// @param {String} $name - The name of the shadow.
@mixin elevation($name) {
box-shadow: var(--ig-elevation-#{$name});
}
47 changes: 47 additions & 0 deletions sass/elevations/presets/_material.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
@use '../index' as *;

////
/// @group elevations
/// @author <a href="https://github.com/simeonoff" target="_blank">Simeon Simeonoff</a>
////

/// Level 1 - Umbra Shadows
/// @type {Color} $color-1 - The color used to generate umbra shadows.
$color-1: rgba(0 0 0 / 26%);

/// Level 2 - Penumbra Shadows
/// @type {Color} $color-2 - The color used to generate penumbra shadows.
$color-2: rgba(0 0 0 / 12%);

/// Level 3 - Ambient Shadows
/// @type {Color} $color-3 - The color used to generate ambient shadows.
$color-3: rgba(0 0 0 / 8%);

/// @type {Map} $elevations - А map of 24 shadow elevations with the umbra, penumbra and ambient shadows.
$elevations: (
0: none,
1: box-shadow((0 1px 3px 0 $color-1, 0 1px 1px 0 $color-2, 0 2px 1px -1px $color-3)),
2: box-shadow((0 1px 5px 0 $color-1, 0 2px 2px 0 $color-2, 0 3px 1px -2px $color-3)),
3: box-shadow((0 1px 8px 0 $color-1, 0 3px 4px 0 $color-2, 0 3px 3px -2px $color-3)),
4: box-shadow((0 2px 4px -1px $color-1, 0 4px 5px 0 $color-2, 0 1px 10px 0 $color-3)),
5: box-shadow((0 3px 5px -1px $color-1, 0 5px 8px 0 $color-2, 0 1px 14px 0 $color-3)),
6: box-shadow((0 3px 5px -1px $color-1, 0 6px 10px 0 $color-2, 0 1px 18px 0 $color-3)),
7: box-shadow((0 4px 5px -2px $color-1, 0 7px 10px 1px $color-2, 0 2px 16px 1px $color-3)),
8: box-shadow((0 5px 5px -3px $color-1, 0 8px 10px 1px $color-2, 0 3px 14px 2px $color-3)),
9: box-shadow((0 5px 6px -3px $color-1, 0 9px 12px 1px $color-2, 0 3px 16px 2px $color-3)),
10: box-shadow((0 6px 6px -3px $color-1, 0 10px 14px 1px $color-2, 0 4px 18px 3px $color-3)),
11: box-shadow((0 6px 7px -4px $color-1, 0 11px 15px 1px $color-2, 0 4px 20px 3px $color-3)),
12: box-shadow((0 7px 8px -4px $color-1, 0 12px 17px 2px $color-2, 0 5px 22px 4px $color-3)),
13: box-shadow((0 7px 8px -4px $color-1, 0 13px 19px 2px $color-2, 0 5px 24px 4px $color-3)),
14: box-shadow((0 7px 9px -4px $color-1, 0 14px 21px 2px $color-2, 0 5px 26px 4px $color-3)),
15: box-shadow((0 8px 9px -5px $color-1, 0 15px 22px 2px $color-2, 0 6px 28px 5px $color-3)),
16: box-shadow((0 8px 10px -5px $color-1, 0 16px 24px 2px $color-2, 0 6px 30px 5px $color-3)),
17: box-shadow((0 8px 11px -5px $color-1, 0 17px 26px 2px $color-2, 0 6px 32px 5px $color-3)),
18: box-shadow((0 9px 11px -5px $color-1, 0 18px 28px 2px $color-2, 0 7px 34px 6px $color-3)),
19: box-shadow((0 9px 12px -6px $color-1, 0 19px 29px 2px $color-2, 0 7px 36px 6px $color-3)),
20: box-shadow((0 10px 13px -6px $color-1, 0 20px 31px 3px $color-2, 0 8px 38px 7px $color-3)),
21: box-shadow((0 10px 13px -6px $color-1, 0 21px 33px 3px $color-2, 0 8px 40px 7px $color-3)),
22: box-shadow((0 10px 14px -6px $color-1, 0 22px 35px 3px $color-2, 0 8px 42px 7px $color-3)),
23: box-shadow((0 11px 14px -7px $color-1, 0 23px 36px 3px $color-2, 0 9px 44px 8px $color-3)),
24: box-shadow((0 11px 15px -7px $color-1, 0 24px 38px 3px $color-2, 0 9px 46px 8px $color-3))
);
69 changes: 69 additions & 0 deletions test/_elevations.spec.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
@use 'sass:meta';
@use 'sass:list';
@use '../node_modules/sass-true/' as *;
@use '../index' as *;

@include describe('Elevations') {
@include it('should return an empty list for a list of non box-shadow values') {
$raw: (pink, yellow, 9px, 'black');
$transformed: box-shadow($raw);
$expected: ();

@include assert-equal($transformed, $expected);
}

@include it('should produce a box shadow that reacts to CSS --ig-elevation-factor changes') {
$raw: (0 0 2px 3px black, 0 6px 9px orange);
$transformed: box-shadow($raw);
$expected: (
0 0 calc($factor * 2px) calc($factor * 3px) black,
0 calc($factor * 6px) calc($factor * 9px) orange
);

@include assert-equal($transformed, $expected);
}

@include it('should produce CSS variables for a map of shadows') {
$shadows: (
small: box-shadow(0 .125rem .25rem rgba(0 0 0 / 75%)),
medium: box-shadow(0 .25rem .5rem rgba(0 0 0 / 85%)),
large: box-shadow(0 .75rem 1rem rgba(0 0 0 / 95%)),
);

@include assert() {
@include output() {
@include elevations($shadows);
}

@include expect() {
@each $key, $value in $shadows {
--ig-elevation-#{$key}: #{$value};
}
}
}
}

@include it('should retrieve a CSS variable elevation by name') {
@include assert() {
@include output() {
box-shadow: elevation(small);
}

@include expect() {
box-shadow: var(--ig-elevation-small);
}
}
}

@include it('should include box-shadow styles for an elevation level') {
@include assert() {
@include output() {
@include elevation(small);
}

@include expect() {
box-shadow: var(--ig-elevation-small);
}
}
}
}
1 change: 1 addition & 0 deletions test/_index.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
@use '../node_modules/sass-true/' as *;
@use 'color.spec' as *;
@use 'typography.spec' as *;
@use 'elevations.spec' as *;
2 changes: 2 additions & 0 deletions test/e2e/theme.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@use '../../index' as *;
@use '../../sass/elevations/presets/material' as *;

$h1: (font-size: 96px);
$h2: (font-size: 70px);
Expand Down Expand Up @@ -34,3 +35,4 @@ $palette: palette($primary: #9fe, $secondary: orange, $surface: #fff);

@include palette($palette);
@include typography("'Roboto', sans-serif", $scale);
@include elevations($elevations);

0 comments on commit 8eb07f5

Please sign in to comment.