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 @@
-
-
-
-
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);
}
}
}