Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(themes): add functions and mixins #6

Merged
merged 4 commits into from
Jul 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
@forward './sass/typography';
@forward './sass/elevations';
@forward './sass/utils';
@forward './sass/themes';
1 change: 1 addition & 0 deletions sass/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
@forward 'elevations';
@forward 'typography';
@forward 'utils';
@forward 'themes';
31 changes: 31 additions & 0 deletions sass/color/_charts.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/// A list of color values to be used as brushes in charts.
/// @type List
/// @access public
$brushes-regular: (
rgb(157 231 114),
rgb(139 91 177),
rgb(109 177 255),
rgb(154 242 228),
rgb(238 88 121),
rgb(115 86 86),
rgb(247 210 98),
rgb(168 168 183),
rgb(224 81 169),
rgb(248 161 95),
);

/// A list of color values to be used as color-blind brushes in charts.
/// @type List
/// @access public
$brushes-color-blind: (
rgb(86 180 233),
rgb(0 158 115),
rgb(240 228 68),
rgb(213 94 0),
rgb(214 0 254),
rgb(0 73 159),
rgb(230 159 0),
rgb(0 0 0),
rgb(132 240 223),
rgb(115 86 86)
);
22 changes: 21 additions & 1 deletion sass/color/_functions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,22 @@
@use 'sass:list';
@use 'sass:color';
@use 'sass:string';
@use 'types';
@use 'charts';
@use 'multipliers';
@use 'types';
@use '../utils' as *;

$_enhanced-accessibility: false;

/// Configures the color module.
/// @access public
/// @param {Boolean} $enhanced-accessibility - Enables features like color blind palettes.
@mixin configure($enhanced-accessibility: null) {
@if $enhanced-accessibility {
$_enhanced-accessibility: $enhanced-accessibility !global;
}
}

/// Generates a color palette.
/// @access public
/// @group Palettes
Expand Down Expand Up @@ -317,3 +329,11 @@
math.pow(math.div($value + .055, 1.055), 2.4)
);
}

/// Returns a list of colors to be used as chart brushes.
/// @access public
/// @group Palettes
/// @returns { List } - A list of colors to be used as chart brushes.
@function chart-brushes() {
@return if($_enhanced-accessibility, charts.$brushes-color-blind, charts.$brushes-regular);
}
1 change: 1 addition & 0 deletions sass/color/_index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
@forward 'mixins';
@forward 'types';
@forward 'multipliers';
@forward 'charts';
101 changes: 101 additions & 0 deletions sass/themes/_functions.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '../utils/map' as *;
@use '../elevations/' as *;
@use '../color/' as color;

/// Digests a theme schema and returns a resolved theme map.
/// @access private
/// @param {Map} $schema - A theme schema.
/// @requires {function} extend
/// @requires {function} resolve-value
/// @example scss Get the resolved theme for a schema
/// $custom-schema: (
/// foreground: (
/// color: ('primary', 800, .5)
/// ),
/// border-radius: rem(5px)
/// );
/// $theme: digest-schema($custom-schema);
/// @returns {Map} - A theme map with resolved values.
@function digest-schema($schema) {
$result: ();

@each $key, $value in $schema {
@if meta.type-of($value) == 'map' {
$result: extend($result, (#{$key}: resolve-value($value)));
} @else {
$result: extend($result, (#{$key}: $value));
}

// Special case for chart elevation literals
@if string.index($key, 'elevation') {
$result: extend(
$result,
(
#{$key}: #{elevation($value)}
)
);
}

// Special case for chart brushes
@if $value == 'series' {
$result: extend(
$result,
(
#{$key}: #{color.chart-brushes()}
)
);
}
}

@return $result;
}

/// Resolves schema values, where the keys of the passed value map are the names
/// of the functions to be called and the value for a given key is the argument
/// the function should be called with.
/// @access private
/// @param {Map} $instructions - The map to be used as instruction set.
/// @example scss Resolve primary 500 color
/// $value: resolve-value((color: (primary, 500)));
/// @returns {dynamic} - The resolved value.
@function resolve-value($instructions) {
$result: ();

@each $fn, $args in $instructions {
$func: if(
meta.function-exists($fn, $module: color),
meta.get-function($fn, $module: color),
null
);

@if $func {
@if $fn == 'color' or $fn == 'contrast-color' {
$result: meta.call($func, null, $args...);
}
}
}

@return $result;
}

/// Retrieves the CSS custom property reference for the given key in the component theme.
/// @access public
/// @param {map} $theme - The source theme to be used to read values from.
/// @param {string} $property - A key from the theme map to assign as value to the property.
/// @example scss Assign the color property in a set of rules to a value from the theme.
/// [part='icon'] {
/// color: var-get($theme, 'icon-color', inherit); // var(--icon-color, inherit)
/// }
/// @returns {String} - The CSS reference of the property in the theme.
@function var-get($theme, $property, $fallback: null) {
@if map.has-key($theme, $property) {
$p: --#{$property};

@return if($fallback, var($p, $fallback), var($p));
} @else {
@error 'The theme for #{map.get($map, 'name')} does not contain #{$key}';
}
}
2 changes: 2 additions & 0 deletions sass/themes/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@forward 'functions';
@forward 'mixins';
60 changes: 60 additions & 0 deletions sass/themes/_mixins.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
@use 'sass:map';
@use 'sass:meta';
@use 'sass:string';
@use '../utils/' as *;
@use '../elevations/' as *;

/// A list of ignored keywords to be excluded when generating CSS variables for a theme.
/// @access private
$ignored-keys: ('name', 'palette', 'variant', 'selector');

/// Parses a map of key value pairs from component themes to css variables.
/// @access private
/// @param {map} $theme - The component theme to be used to generate css variables.
/// @example scss Convert theme colors to CSS variables.
/// $theme: digest-schema((background: color(primary, 500), foreground: contrast-color(color, 500));
/// :root {
/// @include css-vars-from-theme($theme);
/// }
@mixin css-vars-from-theme($theme, $name, $ignored: $ignored-keys) {
$themes: map.get($theme, 'themes');

// This is here only because the button theme consists of 4 nested themes.
@if $themes and meta.type-of($themes) == 'map' {
@each $theme in $themes {
@include css-vars(list.nth($theme, 2));
}
}

@each $key, $value in map.remove($theme, $ignored...) {
@if meta.type-of($value) != 'map' {
--#{$key}: var(--#{$name}-#{$key}, #{$value});
}
}
}

/// Add theme colors as CSS variables to a given scope.
/// @access public
/// @param {map} $theme - The component theme to be used.
/// @param {map} $scope [null] - The CSS variables scope to be used. (optional)
/// @requires {mixin} css-vars-from-theme
@mixin css-vars($theme, $scope: null) {
$s: map.get($theme, 'selector');
$n: map.get($theme, 'name');
$name: if($scope, $scope, $s or $n);

@if not($n) or string.length($n) == 0 {
@error 'Theme should have a non-null or empty name property. Example: theme: (name: my-theme)';
}

@if is-root() {
#{$name} {
@include css-vars-from-theme($theme, $n);
}
} @else {
&,
#{$name} {
@include css-vars-from-theme($theme, $n);
}
}
}
2 changes: 2 additions & 0 deletions sass/typography/_functions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
/// @group Typography
////

$browser-context: 16px;

/// Converts pixels to relative values (em).
/// @access public
/// @param {number|string} $pixels - The pixel value to be converted.
Expand Down
1 change: 1 addition & 0 deletions sass/utils/_index.scss
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
@forward 'math';
@forward 'meta';
@forward 'map';
37 changes: 37 additions & 0 deletions sass/utils/_map.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
@use 'sass:map';

/// Removes all null key-value pairs from a map
/// @access private
/// @param {Map} $map - The target map to be cleaned.
/// @returns {Map} - Returns a map with null key-value pairs removed.
@function clean($map) {
$result: ();

@each $key, $value in $map {
@if $value {
$result: map.merge(
$result,
(
#{$key}: $value
)
);
}
}

@return $result;
}

/// Extends a Map with the values of another Map, disregarding null values in the process.
/// @access public
/// @param {Map...} $maps - The maps to get extended.
/// @requires {function} map-clean
/// @returns {Map} - Returns the merged maps.
@function extend($maps...) {
$result: ();

@each $map in $maps {
$result: map.merge($result, clean($map));
}

@return $result;
}
12 changes: 12 additions & 0 deletions test/_color.spec.scss
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ $_palette: palette(
}
}

@include describe('charts') {
@include it('should resolve regular chart brushes') {
@include configure($enhanced-accessibility: false);
@include assert-equal(chart-brushes(), $brushes-regular);
}

@include it('should resolve color-blind chart brushes') {
@include configure($enhanced-accessibility: true);
@include assert-equal(chart-brushes(), $brushes-color-blind);
}
}

@include describe('contrast') {
@include it('should return the passed background value if no valid colors are provided') {
$value: 'not a color';
Expand Down
3 changes: 2 additions & 1 deletion test/_index.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
@use '../node_modules/sass-true/' as *;
@use 'color.spec' as *;
@use 'typography.spec' as *;
@use 'utils.spec' as *;
@use 'themes.spec' as *;
@use 'elevations.spec' as *;
Loading