diff --git a/app/assets/stylesheets/common/foundation/color_transformations.scss b/app/assets/stylesheets/common/foundation/color_transformations.scss index fa2a1f05408..28d2ced3524 100644 --- a/app/assets/stylesheets/common/foundation/color_transformations.scss +++ b/app/assets/stylesheets/common/foundation/color_transformations.scss @@ -3,24 +3,46 @@ // all variables should have the !default flag //primary -$primary-very-low: dark-light-diff($primary, $secondary, 97%, -82%) !default; -$primary-low: dark-light-diff($primary, $secondary, 90%, -78%) !default; -$primary-low-mid: dark-light-diff($primary, $secondary, 70%, -45%) !default; -$primary-medium: dark-light-diff($primary, $secondary, 50%, -35%) !default; -$primary-high: dark-light-diff($primary, $secondary, 30%, -25%) !default; -$primary-very-high: dark-light-diff($primary, $secondary, 15%, -10%) !default; +@function _dark-primary-shade($units) { + $primary-50-lightness: -72%; + $primary-900-lightness: -8%; + $step: math.div($primary-50-lightness - $primary-900-lightness, 850); + @return $primary-50-lightness - ($step * ($units - 50)); +} -//primary-numbers -$primary-50: dark-light-diff($primary, $secondary, 97%, -82%) !default; -$primary-100: dark-light-diff($primary, $secondary, 94%, -80%) !default; -$primary-200: dark-light-diff($primary, $secondary, 90%, -78%) !default; -$primary-300: dark-light-diff($primary, $secondary, 80%, -60%) !default; -$primary-400: dark-light-diff($primary, $secondary, 70%, -45%) !default; -$primary-500: dark-light-diff($primary, $secondary, 60%, -40%) !default; -$primary-600: dark-light-diff($primary, $secondary, 50%, -35%) !default; -$primary-700: dark-light-diff($primary, $secondary, 38%, -30%) !default; -$primary-800: dark-light-diff($primary, $secondary, 30%, -25%) !default; -$primary-900: dark-light-diff($primary, $secondary, 15%, -10%) !default; +@function _light-primary-shade($units) { + $primary-50-lightness: 90%; + $primary-900-lightness: 18%; + $step: math.div($primary-50-lightness - $primary-900-lightness, 850); + @return $primary-50-lightness - ($step * ($units - 50)); +} + +@function _numbered-primary($units) { + @return dark-light-diff( + $primary, + $secondary, + _light-primary-shade($units), + _dark-primary-shade($units) + ); +} + +$primary-50: _numbered-primary(50) !default; +$primary-100: _numbered-primary(100) !default; +$primary-200: _numbered-primary(200) !default; +$primary-300: _numbered-primary(300) !default; +$primary-400: _numbered-primary(400) !default; +$primary-500: _numbered-primary(500) !default; +$primary-600: _numbered-primary(600) !default; +$primary-700: _numbered-primary(700) !default; +$primary-800: _numbered-primary(800) !default; +$primary-900: _numbered-primary(900) !default; + +$primary-very-low: $primary-50 !default; +$primary-low: $primary-200 !default; +$primary-low-mid: $primary-400 !default; +$primary-medium: $primary-600 !default; +$primary-high: $primary-800 !default; +$primary-very-high: $primary-900 !default; $header_primary-low: blend-header-primary-background(10%) !default; $header_primary-low-mid: blend-header-primary-background(35%) !default; diff --git a/app/assets/stylesheets/common/foundation/oklab.scss b/app/assets/stylesheets/common/foundation/oklab.scss new file mode 100644 index 00000000000..562393a4d98 --- /dev/null +++ b/app/assets/stylesheets/common/foundation/oklab.scss @@ -0,0 +1,68 @@ +@use "sass:math"; +@use "sass:color"; +@use "sass:map"; + +/** + Adapted from https://bottosson.github.io/posts/colorwrong and https://bottosson.github.io/posts/oklab/ + (public domain) +*/ + +@function component-to-nonninear($x) { + @if $x >= 0.0031308 { + @return (1.055) * math.pow($x, math.div(1, 2.4)) - 0.055; + } @else { + @return 12.92 * $x; + } +} + +@function component-to-linear($x) { + @if ($x >= 0.04045) { + @return math.pow(math.div($x + 0.055, 1 + 0.055), 2.4); + } @else { + @return math.div($x, 12.92); + } +} + +@function rgb_to_oklab($color) { + $r: component-to-linear(math.div(color.red($color), 255)); + $g: component-to-linear(math.div(color.green($color), 255)); + $b: component-to-linear(math.div(color.blue($color), 255)); + + $l: 0.4122214708 * $r + 0.5363325363 * $g + 0.0514459929 * $b; + $m: 0.2119034982 * $r + 0.6806995451 * $g + 0.1073969566 * $b; + $s: 0.0883024619 * $r + 0.2817188376 * $g + 0.6299787005 * $b; + + $l_: math.pow($l, math.div(1, 3)); + $m_: math.pow($m, math.div(1, 3)); + $s_: math.pow($s, math.div(1, 3)); + + @return ( + "L": 0.2104542553 * $l_ + 0.793617785 * $m_ - 0.0040720468 * $s_, + "a": 1.9779984951 * $l_ - 2.428592205 * $m_ + 0.4505937099 * $s_, + "b": 0.0259040371 * $l_ + 0.7827717662 * $m_ - 0.808675766 * $s_ + ); +} + +@function oklab_to_rgb($oklab) { + $L: map.get($oklab, "L"); + $a: map.get($oklab, "a"); + $b: map.get($oklab, "b"); + + $l_: $L + 0.3963377774 * $a + 0.2158037573 * $b; + $m_: $L - 0.1055613458 * $a - 0.0638541728 * $b; + $s_: $L - 0.0894841775 * $a - 1.291485548 * $b; + + $l: math.pow($l_, 3); + $m: math.pow($m_, 3); + $s: math.pow($s_, 3); + + $linear_r: +4.0767416621 * $l - 3.3077115913 * $m + 0.2309699292 * $s; + $linear_g: -1.2684380046 * $l + 2.6097574011 * $m - 0.3413193965 * $s; + $linear_b: -0.0041960863 * $l - 0.7034186147 * $m + 1.707614701 * $s; + + $r: component-to-nonninear($linear_r); + $g: component-to-nonninear($linear_g); + $b: component-to-nonninear($linear_b); + + @return rgb($r * 255, $g * 255, $b * 255); +} diff --git a/app/assets/stylesheets/common/foundation/variables.scss b/app/assets/stylesheets/common/foundation/variables.scss index 5cf234edd63..b7a20906beb 100644 --- a/app/assets/stylesheets/common/foundation/variables.scss +++ b/app/assets/stylesheets/common/foundation/variables.scss @@ -7,6 +7,8 @@ // -------------------------------------------------- @use "sass:math"; +@use "sass:map"; +@use "./oklab" as oklab; $small-width: 800px !default; $medium-width: 995px !default; @@ -179,11 +181,42 @@ $z-layers: ( @if dc-color-brightness($adjusted-color) < dc-color-brightness($comparison-color) { - @return scale-color($adjusted-color, $lightness: $lightness); + @return oklab-scale-color($adjusted-color, $lightness: $lightness); } @else { - @return scale-color($adjusted-color, $lightness: $darkness); + @return oklab-scale-color($adjusted-color, $lightness: $darkness); } } + +/** + Scale a colour's luminance using the oklab color space. Eventually, this could be implemented + in the browser using css Relative Color Syntax. In native CSS, this function is equivelant to: + + ```css + // For lightness > 0 + oklab(from var(--color) calc(L + ((1-L) * var(--lightness))) a b) + // For lightness < 0 + oklab(from var(--color) calc(L + (L * var(--lightness)) a b) + ``` +**/ +@function oklab-scale-color($color, $lightness: 0) { + $current-oklab: oklab.rgb_to_oklab($color); + $current-lightness: map.get($current-oklab, "L"); + + $new-lightness: null; + @if ($lightness > 0) { + $new-lightness: $current-lightness + + ((1 - $current-lightness) * math.div($lightness, 100%)); + } @else { + $new-lightness: $current-lightness + + ($current-lightness * math.div($lightness, 100%)); + } + + $transformed-oklab: map.set($current-oklab, "L", $new-lightness); + $transformed-rgb: oklab.oklab-to-rgb($transformed-oklab); + + @return $transformed-rgb; +} + @function dark-light-choose($light-theme-result, $dark-theme-result) { @if is-light-color-scheme() { @return $light-theme-result; diff --git a/lib/stylesheet/watcher.rb b/lib/stylesheet/watcher.rb index 9740758d076..6384146826f 100644 --- a/lib/stylesheet/watcher.rb +++ b/lib/stylesheet/watcher.rb @@ -76,6 +76,7 @@ module Stylesheet target = nil target_match = long.match(/admin|desktop|mobile|publish|wizard|wcag|color_definitions/) + target_match ||= "color_definitions" if long.match(/color_transformations/) target = target_match[0] if target_match&.length { basename: File.basename(long), target: target, plugin_name: plugin_name } diff --git a/plugins/styleguide/assets/javascripts/discourse/components/color-example.hbs b/plugins/styleguide/assets/javascripts/discourse/components/color-example.hbs index b946fa36329..33510b55cb4 100644 --- a/plugins/styleguide/assets/javascripts/discourse/components/color-example.hbs +++ b/plugins/styleguide/assets/javascripts/discourse/components/color-example.hbs @@ -1,4 +1,4 @@
-
var(--{{@color}})
+
{{@color}}
\ No newline at end of file diff --git a/plugins/styleguide/assets/javascripts/discourse/components/sections/atoms/03-colors.hbs b/plugins/styleguide/assets/javascripts/discourse/components/sections/atoms/03-colors.hbs index e4b06cec732..7185f4a714c 100644 --- a/plugins/styleguide/assets/javascripts/discourse/components/sections/atoms/03-colors.hbs +++ b/plugins/styleguide/assets/javascripts/discourse/components/sections/atoms/03-colors.hbs @@ -3,8 +3,6 @@ - -
@@ -19,8 +17,6 @@ -
-
@@ -55,8 +51,6 @@ -
-
diff --git a/plugins/styleguide/assets/stylesheets/styleguide.scss b/plugins/styleguide/assets/stylesheets/styleguide.scss index cc799b631c1..4bc4fee9a3e 100644 --- a/plugins/styleguide/assets/stylesheets/styleguide.scss +++ b/plugins/styleguide/assets/stylesheets/styleguide.scss @@ -128,26 +128,27 @@ } .color-row { display: flex; + border: 1px solid black; .color-example { flex: 1; display: flex; flex-direction: column; height: 120px; - margin: 0.5em 0.5em 0.5em 0; - border: 1px solid var(--primary-300); + // margin: 0.5em 0.5em 0.5em 0; + // border: 1px solid black; .color-bg { flex: 4; - border-bottom: 1px solid var(--primary-300); + // border-bottom: 1px solid var(--primary-300); } .color-name { flex: 1; display: flex; align-items: center; - padding: 0.25em 0.5em; - font-weight: 700; - font-size: var(--font-down-1); + // padding: 0.25em 0.5em; + // font-weight: 700; + font-size: var(--font-down-2); } } }