From 1c7272be54be8783d81dd25900c6c7dc9beca09d Mon Sep 17 00:00:00 2001 From: Volpeon Date: Sun, 13 Feb 2022 10:15:46 +0100 Subject: Better palette generation algorithm --- src/_functions.scss | 45 +++++++++++++++++++++++++++ src/_vars.scss | 90 +++++++++++++++++++++-------------------------------- 2 files changed, 80 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/_functions.scss b/src/_functions.scss index 9425413..73a1ec9 100644 --- a/src/_functions.scss +++ b/src/_functions.scss @@ -1,4 +1,7 @@ +@use 'sass:math'; @use 'iro-sass/src/index' as iro; +@use '@oddbird/blend'; +@use '@oddbird/blend/sass/convert' as blend-convert; @function color($key, $tree: 'colors', $default: null, $global: false) { @return iro.props-get(join(--colors, $key), $tree, $default, $global); @@ -59,3 +62,45 @@ } } } + +@function multi-contrast($base-color, $colors, $wanted-contrasts) { + $dir: if(lightness($base-color) >= 50%, -1, 1); + $base-lum: nth(blend-convert.lin_sRGB_to_XYZ(blend-convert.lin_sRGB(blend-convert.sassToRgb($base-color))), 2) + .05; + + $result: (); + $colors-len: length($colors); + $colors-idx: if($dir == -1, $colors-len, 1); + $wanted-len: length($wanted-contrasts); + $wanted-idx: 1; + + @while $colors-idx >= 1 and $colors-idx <= $colors-len and $wanted-idx <= $wanted-len { + $color: nth($colors, $colors-idx); + $lum: nth(blend-convert.lin_sRGB_to_XYZ(blend-convert.lin_sRGB(blend-convert.sassToRgb($color))), 2) + .05; + $contrast: math.div(math.max($base-lum, $lum), math.min($lum, $base-lum)); + + @if $contrast != 1 { + $contrast: $dir * $contrast; + + @if $lum <= $base-lum { + $contrast: -1 * $contrast; + } + } + + $wanted-contrast: nth($wanted-contrasts, $wanted-idx); + + @if $contrast >= $wanted-contrast { + $result: append($result, $color); + $wanted-idx: $wanted-idx + 1; + } @else { + $colors-idx: $colors-idx + $dir * 1; + } + } + + $last-color: nth($colors, if($dir == -1, 1, $colors-len)); + + @for $i from $wanted-idx through $wanted-len { + $result: append($result, $last-color); + } + + @return $result; +} diff --git a/src/_vars.scss b/src/_vars.scss index cafdb3d..569d535 100644 --- a/src/_vars.scss +++ b/src/_vars.scss @@ -1,4 +1,4 @@ -@use 'sass:math'; +@use 'sass:map'; @use 'iro-sass/src/index' as iro; @use 'include-media/dist/include-media' as media; @use '@oddbird/blend'; @@ -21,37 +21,45 @@ media.$unit-intervals: ( $grays: (); @for $i from 0 through 100 { - $grays: append($grays, $i * 1%); + $grays: append($grays, blend.lch($i * 1% 0 0)); } -$grays-rev: iro.fn-list-reverse($grays); - -@function find-gray($lightness, $contrast) { - $base: blend.lch($lightness 0 0); - $dir: if($contrast < 0, -1, 1) * if($lightness >= 50%, 1, -1); - $args: (); - - @if $dir == 1 { - @each $gray in $grays-rev { - @if $gray < $lightness { - $args: append($args, blend.lch($gray 0 0)); - } - } - } @else { - @each $gray in $grays { - @if $gray > $lightness { - $args: append($args, blend.lch($gray 0 0)); - } - } - } +$wanted-grays: ( + -1.1, + -1.05, + 1, + 1.15, + 1.37, + 1.73, + 2.4, + 3.26, + 7.14, + 11, + 17.4, +); + +@function accent-palette($base, $dir: 1) { + @return ( + --hi: blend.scale($base, $lightness: $dir * 15%, $chroma: $dir * 10%), + --main: $base, + --lo: blend.scale($base, $lightness: $dir * -15%, $chroma: $dir * -10%), + --lo2: blend.scale($base, $lightness: $dir * -25%, $chroma: $dir * -20%), + --semi: rgba($base, .4), + --selection: rgba($base, .99), + --fg: blend.contrast($base, #fff, #000), + ); +} + +@function gray-palette($lightness) { + $colors: fn.multi-contrast(blend.lch($lightness * 1% 0 0), $grays, $wanted-grays); + + $palette: (); - @if length($args) == 0 { - @return $base; + @for $i from 1 through length($colors) { + $palette: map.set($palette, --gray#{$i}, hsl(fn.color(--gray-h), fn.color(--gray-s), lightness(nth($colors, $i)))); } - $args: append($args, math.abs($contrast)); - $result: blend.contrast($base, $args...); - @return hsl(fn.color(--gray-h), fn.color(--gray-s), lightness($result)); + @return $palette; } // @@ -120,34 +128,6 @@ $grays-rev: iro.fn-list-reverse($grays); // -@function accent-palette($base, $dir: 1) { - @return ( - --hi: blend.scale($base, $lightness: $dir * 15%, $chroma: $dir * 10%), - --main: $base, - --lo: blend.scale($base, $lightness: $dir * -15%, $chroma: $dir * -10%), - --lo2: blend.scale($base, $lightness: $dir * -25%, $chroma: $dir * -20%), - --semi: rgba($base, .4), - --selection: rgba($base, .99), - --fg: blend.contrast($base, #fff, #000), - ); -} - -@function gray-palette($lightness) { - @return ( - --gray1: find-gray($lightness, -1.1), - --gray2: find-gray($lightness, -1.05), - --gray3: find-gray($lightness, 1), - --gray4: find-gray($lightness, 1.15), - --gray5: find-gray($lightness, 1.37), - --gray6: find-gray($lightness, 1.73), - --gray7: find-gray($lightness, 2.4), - --gray8: find-gray($lightness, 3.26), - --gray9: find-gray($lightness, 7.14), - --gray10: find-gray($lightness, 11), - --gray11: find-gray($lightness, 17.4), - ); -} - @include iro.fn-execute { @include iro.props-store(( --colors: ( -- cgit v1.2.3-70-g09d2