diff --git a/.changeset/metal-geese-swim.md b/.changeset/metal-geese-swim.md new file mode 100644 index 0000000000..7f3b1db1d5 --- /dev/null +++ b/.changeset/metal-geese-swim.md @@ -0,0 +1,5 @@ +--- +'@swisspost/design-system-styles': patch +--- + +Fixed colors of validation icon in HCM on form elements. diff --git a/packages/styles/src/components/form-input.scss b/packages/styles/src/components/form-input.scss index c51862336e..8bbdcfc27e 100644 --- a/packages/styles/src/components/form-input.scss +++ b/packages/styles/src/components/form-input.scss @@ -192,13 +192,7 @@ input.form-control { } } - &.is-valid:not(:disabled) { - background-image: forms.$valid-icon; - } - - &.is-invalid:not(:disabled) { - background-image: forms.$invalid-icon; - } + @include forms-mx.validation-icons; } .form-label:has(+ input.form-control[disabled]) { diff --git a/packages/styles/src/components/form-select.scss b/packages/styles/src/components/form-select.scss index b557ef2570..050c60efc5 100644 --- a/packages/styles/src/components/form-select.scss +++ b/packages/styles/src/components/form-select.scss @@ -1,10 +1,12 @@ @forward './../variables/options'; @use './../mixins/utilities'; -@use './../mixins/forms'; +@use './../functions/forms' as forms-fx; +@use './../mixins/forms' as forms-mx; @use './../functions/tokens'; @use './../tokens/components'; @use './../tokens/elements'; +@use './../variables/components/forms'; tokens.$default-map: components.$post-select; @@ -26,7 +28,7 @@ tokens.$default-map: components.$post-select; border-color: tokens.get('select-color-enabled-border'); border-radius: tokens.get('select-border-radius'); color: tokens.get('select-color-enabled-fg'); - @include forms.select-bg-image('enabled'); + background-image: forms-fx.select-arrow-icon('enabled'); &:disabled { opacity: 1; @@ -36,7 +38,7 @@ tokens.$default-map: components.$post-select; border-style: tokens.get('select-border-style-disabled'); &:not([multiple]) { - @include forms.select-bg-image('disabled'); + background-image: forms-fx.select-arrow-icon('disabled'); } } @@ -45,7 +47,7 @@ tokens.$default-map: components.$post-select; background-color: tokens.get('select-color-selected-bg'); color: tokens.get('select-color-selected-fg'); border-color: tokens.get('select-color-selected-border'); - @include forms.select-bg-image('selected'); + background-image: forms-fx.select-arrow-icon('selected'); @include utilities.focus-style; @@ -60,7 +62,7 @@ tokens.$default-map: components.$post-select; border-color: tokens.get('select-color-hover-border'); &:not([multiple]) { - @include forms.select-bg-image('hover'); + background-image: forms-fx.select-arrow-icon('hover'); } @include utilities.high-contrast-mode { @@ -90,29 +92,53 @@ tokens.$default-map: components.$post-select; } &.is-valid:not(:disabled) { - @include forms.select-bg-image('enabled', 'valid'); + background-image: forms-fx.select-arrow-icon('enabled'), forms.$valid-icon; &:focus { - @include forms.select-bg-image('selected', 'valid'); + background-image: forms-fx.select-arrow-icon('selected'), forms.$valid-icon; } &:hover { &:not([multiple]) { - @include forms.select-bg-image('hover', 'valid'); + background-image: forms-fx.select-arrow-icon('hover'), forms.$valid-icon; + } + } + + &, + &:hover:not([multiple]), + &:focus { + @include utilities.high-contrast-mode-dark() { + background-image: forms-fx.select-arrow-icon('enabled'), forms-fx.valid-icon('#e0e0e0'); + } + + @include utilities.high-contrast-mode-light() { + background-image: forms-fx.select-arrow-icon('enabled'), forms-fx.valid-icon('#333333'); } } } &.is-invalid:not(:disabled) { - @include forms.select-bg-image('enabled', 'invalid'); + background-image: forms-fx.select-arrow-icon('enabled'), forms.$invalid-icon; &:focus { - @include forms.select-bg-image('selected', 'invalid'); + background-image: forms-fx.select-arrow-icon('selected'), forms.$invalid-icon; } &:hover { &:not([multiple]) { - @include forms.select-bg-image('hover', 'invalid'); + background-image: forms-fx.select-arrow-icon('hover'), forms.$invalid-icon; + } + } + + &, + &:hover:not([multiple]), + &:focus { + @include utilities.high-contrast-mode-dark() { + background-image: forms-fx.select-arrow-icon('enabled'), forms-fx.invalid-icon('#e0e0e0'); + } + + @include utilities.high-contrast-mode-light() { + background-image: forms-fx.select-arrow-icon('enabled'), forms-fx.invalid-icon('#333333'); } } } @@ -126,13 +152,7 @@ tokens.$default-map: components.$post-select; background-position: center right tokens.get('select-validation-icon-position-inline-end'); } - &.is-valid:not(:disabled) { - @include forms.select-bg-image($validation: 'valid'); - } - - &.is-invalid:not(:disabled) { - @include forms.select-bg-image($validation: 'invalid'); - } + @include forms-mx.validation-icons(); } } @@ -224,43 +244,43 @@ tokens.$default-map: components.$post-select; [data-color-scheme='dark'] { .form-select:not([multiple]) { - @include forms.select-bg-image('enabled', null, 'dark'); + background-image: forms-fx.select-arrow-icon('enabled', 'dark'); &:disabled { - @include forms.select-bg-image('disabled', null, 'dark'); + background-image: forms-fx.select-arrow-icon('disabled', 'dark'); } &:not(:disabled) { &:focus { - @include forms.select-bg-image('selected', null, 'dark'); + background-image: forms-fx.select-arrow-icon('selected', 'dark'); } &:hover { - @include forms.select-bg-image('hover', null, 'dark'); + background-image: forms-fx.select-arrow-icon('hover', 'dark'); } } &.is-valid:not(:disabled) { - @include forms.select-bg-image('enabled', 'valid', 'dark'); + background-image: forms-fx.select-arrow-icon('enabled', 'dark'), forms.$valid-icon; &:focus { - @include forms.select-bg-image('selected', 'valid', 'dark'); + background-image: forms-fx.select-arrow-icon('selected', 'dark'), forms.$valid-icon; } &:hover { - @include forms.select-bg-image('hover', 'valid', 'dark'); + background-image: forms-fx.select-arrow-icon('hover', 'dark'), forms.$valid-icon; } } &.is-invalid:not(:disabled) { - @include forms.select-bg-image('enabled', 'invalid', 'dark'); + background-image: forms-fx.select-arrow-icon('enabled', 'dark'), forms.$invalid-icon; &:focus { - @include forms.select-bg-image('selected', 'invalid', 'dark'); + background-image: forms-fx.select-arrow-icon('selected', 'dark'), forms.$invalid-icon; } &:hover { - @include forms.select-bg-image('hover', 'invalid', 'dark'); + background-image: forms-fx.select-arrow-icon('hover', 'dark'), forms.$invalid-icon; } } } diff --git a/packages/styles/src/components/form-textarea.scss b/packages/styles/src/components/form-textarea.scss index bec86c5fad..2f54dbed56 100644 --- a/packages/styles/src/components/form-textarea.scss +++ b/packages/styles/src/components/form-textarea.scss @@ -86,13 +86,7 @@ textarea.form-control { } } - &.is-valid:not(:disabled) { - background-image: forms.$valid-icon; - } - - &.is-invalid:not(:disabled) { - background-image: forms.$invalid-icon; - } + @include forms-mx.validation-icons; } .form-label:has(+ textarea.form-control[disabled]) { diff --git a/packages/styles/src/functions/_forms.scss b/packages/styles/src/functions/_forms.scss index 183f1d7d2f..376831a38a 100644 --- a/packages/styles/src/functions/_forms.scss +++ b/packages/styles/src/functions/_forms.scss @@ -1,7 +1,12 @@ -// Source: https://kovart.github.io/dashed-border-generator/ + added stroke-vector-effect +@use 'sass:map'; + @use './color'; @use '../functions/tokens'; +@use '../functions/icons'; +@use '../functions/utilities'; +@use '../variables/components/forms'; +// Source: https://kovart.github.io/dashed-border-generator/ + added stroke-vector-effect @function get-background-svg-stroke( $type, $color, @@ -25,3 +30,39 @@ $svg-additional-attributes + " fill='none' stroke='" + #{color.encode-uri-color($color)} + "' stroke-width='" + $stroke-width "' stroke-dasharray='" + $stroke-dasharray + "'" + $stroke-pathlength-attribute + ' /%3e%3c/svg%3e'; } + +@function select-arrow-icon($state: null, $mode: 'light') { + // Hardcoded colors because CSS variables cannot be used as fill color of background-image + $arrow-color-map: ( + 'enabled-light': #050400, + 'enabled-dark': #fff, + 'hover-light': #504f4b, + 'hover-dark': #fff, + 'selected-light': #050400, + 'selected-dark': #fff, + 'disabled-light': #696864, + 'disabled-dark': #fff, + ); + + @if ($state) { + $state: url('#{icons.get-colored-svg-url('2052', map.get($arrow-color-map, '#{$state}-#{$mode}'))}'); + } + + @return $state; +} + +@function encode-color($color) { + @return utilities.replace($color, '#', '%23'); +} + +@function valid-icon($color) { + $encoded-color: encode-color($color); + $icon: utilities.replace(forms.$valid-icon, '%23107800', $encoded-color); + @return $icon; +} + +@function invalid-icon($color) { + $encoded-color: encode-color($color); + $icon: utilities.replace(forms.$invalid-icon, '%23B20000', $encoded-color); + @return $icon; +} diff --git a/packages/styles/src/mixins/_forms.scss b/packages/styles/src/mixins/_forms.scss index 0854d6adf0..e22b4d2d62 100644 --- a/packages/styles/src/mixins/_forms.scss +++ b/packages/styles/src/mixins/_forms.scss @@ -2,6 +2,7 @@ @use './../variables/components/forms'; @use './../mixins/utilities'; @use './../functions/icons'; +@use './../functions/forms' as forms-fx; @use './../functions/utilities' as utilities-fx; // Placeholder in input fields @@ -30,29 +31,31 @@ } } -@mixin select-bg-image($state: null, $validation: null, $mode: 'light') { - // Hardcoded colors because CSS variables cannot be used as fill color of background-image - $arrow-color-map: ( - 'enabled-light': #050400, - 'enabled-dark': #fff, - 'hover-light': #504f4b, - 'hover-dark': #fff, - 'selected-light': #050400, - 'selected-dark': #fff, - 'disabled-light': #696864, - 'disabled-dark': #fff, - ); +// Used on form elements to set the correct colored validation icon +@mixin validation-icons() { + &.is-valid:not(:disabled) { + background-image: forms.$valid-icon; - @if ($validation == 'valid') { - $validation: forms.$valid-icon; - } @else if ($validation == 'invalid') { - $validation: forms.$invalid-icon; + @include utilities.high-contrast-mode-dark() { + background-image: forms-fx.valid-icon('#e0e0e0'); + } + + @include utilities.high-contrast-mode-light() { + background-image: forms-fx.valid-icon('#333333'); + } } - @if ($state) { - $state: url('#{icons.get-colored-svg-url('2052', map.get($arrow-color-map, '#{$state}-#{$mode}'))}'); + &.is-invalid:not(:disabled) { + background-image: forms.$invalid-icon; + + @include utilities.high-contrast-mode-dark() { + background-image: forms-fx.invalid-icon('#e0e0e0'); + } + + @include utilities.high-contrast-mode-light() { + background-image: forms-fx.invalid-icon('#333333'); + } } - background-image: $state, $validation; } @mixin textarea-resizer-svg($color) { diff --git a/packages/styles/src/mixins/_utilities.scss b/packages/styles/src/mixins/_utilities.scss index 4eb10fd3a0..71cc9442aa 100644 --- a/packages/styles/src/mixins/_utilities.scss +++ b/packages/styles/src/mixins/_utilities.scss @@ -82,6 +82,20 @@ } } +@mixin high-contrast-mode-dark() { + @media (forced-colors: active) and (prefers-color-scheme: dark), + (-ms-high-contrast: white-on-black) { + @content; + } +} + +@mixin high-contrast-mode-light() { + @media (forced-colors: active) and (prefers-color-scheme: light), + (-ms-high-contrast: black-on-white) { + @content; + } +} + @mixin not-disabled-focus-hover { &:focus, &:not(:disabled):hover,