diff --git a/packages/web/src/scss/components/Checkbox/_Checkbox.scss b/packages/web/src/scss/components/Checkbox/_Checkbox.scss index f3de871201..3da73a8351 100644 --- a/packages/web/src/scss/components/Checkbox/_Checkbox.scss +++ b/packages/web/src/scss/components/Checkbox/_Checkbox.scss @@ -1,4 +1,10 @@ -@use 'sass:map'; +// 1. We allow descending specificity order here because we don't want to set the background-image with SVG twice +// and therefore bloating the CSS. +// 2. We need to set the background-color of the non-disabled Checkbox input to initial color when it is hovered +// or active, because we need it contrasting with the background color. +// 3. We need to set the color of the validation text and helper text to inherit when the Item is hovered or active, +// because we need it contrasting with the background color. + @use 'theme'; @use '../../theme/form-fields' as form-fields-theme; @use '../../tools/form-fields' as form-fields-tools; @@ -37,17 +43,20 @@ $_field-name: 'Checkbox'; background-position: center; background-size: contain; background-repeat: no-repeat; + background-color: form-fields-theme.$input-background-color; + + &:checked, + &:indeterminate { + border-color: form-fields-theme.$inline-field-input-border-color-checked; + background-color: form-fields-theme.$inline-field-input-background-color-checked; + } &:checked { - color: form-fields-theme.$inline-field-input-color-checked; background-image: svg.escape(theme.$input-checked-mark); - background-color: form-fields-theme.$inline-field-input-color-checked; } &:indeterminate { - color: form-fields-theme.$inline-field-input-color-checked; background-image: svg.escape(theme.$input-indeterminate-mark); - background-color: form-fields-theme.$inline-field-input-color-checked; } } @@ -62,60 +71,77 @@ $_field-name: 'Checkbox'; @include form-fields-tools.input-field-validation-states($_field-name); -.Checkbox--disabled { - @include form-fields-tools.inline-field-root-disabled(); -} +.Checkbox--item { + @include form-fields-tools.item(); -.Checkbox--disabled .Checkbox__label { - @include form-fields-tools.label-disabled(); + display: flex; } -.Checkbox--disabled .Checkbox__validationText { - @include form-fields-tools.validation-text-disabled(); +.Checkbox--item .Checkbox__label { + @include form-fields-tools.item-label(); } -.Checkbox--disabled .Checkbox__helperText { - @include form-fields-tools.helper-text-disabled(); +.Checkbox--item .Checkbox__validationText { + @include form-fields-tools.item-validation-text(); } -.Checkbox--disabled > .Checkbox__input, -.Checkbox > .Checkbox__input:disabled { - @include form-fields-tools.input-disabled(); +.Checkbox--item .Checkbox__helperText { + @include form-fields-tools.item-helper-text(); } -.Checkbox--disabled > .Checkbox__input:checked, -.Checkbox--disabled > .Checkbox__input:indeterminate, -.Checkbox > .Checkbox__input:disabled:checked, -.Checkbox > .Checkbox__input:disabled:indeterminate { - background-color: form-fields-theme.$input-color-disabled; +.Checkbox--item:is(.Checkbox--disabled, .Checkbox.is-disabled) { + @include form-fields-tools.item-disabled(); } -.Checkbox--item { - @include form-fields-tools.item(); +:is(.Checkbox--disabled, .Checkbox.is-disabled) { + @include form-fields-tools.inline-field-root-disabled(); +} - display: flex; +:is(.Checkbox--disabled, .Checkbox.is-disabled) .Checkbox__label { + @include form-fields-tools.label-disabled(); } -.Checkbox--item.Checkbox--disabled { - @include form-fields-tools.item-disabled(); +:is(.Checkbox--disabled, .Checkbox.is-disabled) .Checkbox__validationText { + @include form-fields-tools.validation-text-disabled(); } -// stylelint-disable-next-line selector-max-class, selector-max-compound-selectors, selector-max-specificity -- We need to override the default styles for the label in Item. -.Checkbox--item .Checkbox__input:checked ~ .Checkbox__text > .Checkbox__label { - @include form-fields-tools.item-label-checked(); +:is(.Checkbox--disabled, .Checkbox.is-disabled) .Checkbox__helperText { + @include form-fields-tools.helper-text-disabled(); } -.Checkbox--item .Checkbox__validationText { - @include form-fields-tools.item-validation-text(); +:is(.Checkbox--disabled, .Checkbox.is-disabled) > .Checkbox__input, +.Checkbox > .Checkbox__input:disabled { + @include form-fields-tools.input-disabled(); + + border-color: form-fields-theme.$input-border-color-disabled; + background-color: form-fields-theme.$input-background-color-disabled; + + &:checked, + &:indeterminate { + border-color: form-fields-theme.$inline-field-input-border-color-checked-disabled; + } + + &:checked { + background-image: svg.escape(theme.$input-checked-mark-disabled); + } + + // stylelint-disable-next-line no-descending-specificity -- 1. + &:indeterminate { + background-image: svg.escape(theme.$input-indeterminate-mark-disabled); + } } -.Checkbox--item .Checkbox__helperText { - @include form-fields-tools.item-helper-text(); +// stylelint-disable selector-max-specificity -- 2. +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled) .Checkbox__input:hover:not(:checked), +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled) .Checkbox__input:active:not(:checked) { + background-color: form-fields-theme.$input-background-color; } -.Checkbox--item:not(.Checkbox--disabled):hover .Checkbox__validationText, -.Checkbox--item:not(.Checkbox--disabled):active .Checkbox__validationText, -.Checkbox--item:not(.Checkbox--disabled):hover .Checkbox__helperText, -.Checkbox--item:not(.Checkbox--disabled):active .Checkbox__helperText { +// 3. +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled):hover .Checkbox__validationText, +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled):active .Checkbox__validationText, +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled):hover .Checkbox__helperText, +.Checkbox--item:not(.Checkbox--disabled, .Checkbox.is-disabled):active .Checkbox__helperText { color: inherit; } +// stylelint-enable selector-max-specificity diff --git a/packages/web/src/scss/components/Checkbox/_theme.scss b/packages/web/src/scss/components/Checkbox/_theme.scss index 8d91d567ef..c235d2a59c 100644 --- a/packages/web/src/scss/components/Checkbox/_theme.scss +++ b/packages/web/src/scss/components/Checkbox/_theme.scss @@ -1,7 +1,10 @@ -@use '@tokens' as tokens; +@use '@global' as global-tokens; +@use '../../settings/globals'; -$input-border-radius: 2px; +$input-border-radius: global-tokens.$radius-200; $input-width: 18px; $input-margin: 3px; -$input-checked-mark: url('data:image/svg+xml,'); -$input-indeterminate-mark: url('data:image/svg+xml,'); +$input-checked-mark: var(--#{globals.$prefix}checkbox-input-background-image-url); +$input-checked-mark-disabled: var(--#{globals.$prefix}checkbox-input-disabled-background-image-url); +$input-indeterminate-mark: var(--#{globals.$prefix}checkbox-input-indeterminate-background-image-url); +$input-indeterminate-mark-disabled: var(--#{globals.$prefix}checkbox-input-indeterminate-disabled-background-image-url); diff --git a/packages/web/src/scss/components/index.scss b/packages/web/src/scss/components/index.scss index 7230cadad1..e559d4541c 100644 --- a/packages/web/src/scss/components/index.scss +++ b/packages/web/src/scss/components/index.scss @@ -3,8 +3,7 @@ @forward 'Alert'; @forward 'Breadcrumbs'; @forward 'Button'; - -// @forward 'Checkbox'; +@forward 'Checkbox'; @forward 'Collapse'; @forward 'Container'; @forward 'Divider'; diff --git a/packages/web/src/scss/theme/_form-fields.scss b/packages/web/src/scss/theme/_form-fields.scss index ee1711ce21..5d01c1ad36 100644 --- a/packages/web/src/scss/theme/_form-fields.scss +++ b/packages/web/src/scss/theme/_form-fields.scss @@ -1,56 +1,57 @@ -@use '@tokens' as tokens; +@use '@global' as global-tokens; +@use '../settings/globals'; // Common for all form components -$gap: tokens.$space-400; -$input-typography: tokens.$body-medium-text-regular; -$input-color-disabled: tokens.$text-primary-disabled; -$input-border-color-success: tokens.$emotion-success-default; -$input-border-color-warning: tokens.$emotion-warning-default; -$input-border-color-danger: tokens.$emotion-danger-default; -$input-focus-shadow: tokens.$focus; -$label-color-default: tokens.$text-primary-default; -$label-color-disabled: tokens.$text-primary-disabled; -$label-required-margin-left: tokens.$space-200; -$label-required-color: tokens.$emotion-danger-default; -$validation-text-typography: tokens.$body-medium-text-regular; -$validation-text-margin-top: tokens.$space-300; -$validation-text-color-default: tokens.$text-secondary-default; -$validation-text-color-disabled: tokens.$text-secondary-disabled; -$validation-text-color-success: tokens.$emotion-success-default; -$validation-text-color-warning: tokens.$emotion-warning-default; -$validation-text-color-danger: tokens.$emotion-danger-default; -$helper-text-typography: tokens.$body-small-text-regular; -$helper-text-margin-top: tokens.$space-300; -$helper-text-color-default: tokens.$text-secondary-default; -$helper-text-color-disabled: tokens.$text-secondary-disabled; +$gap: global-tokens.$space-500; +$input-typography: global-tokens.$body-medium-regular; +$input-color-disabled: var(--#{globals.$prefix}color-disabled-content); +$input-background-color: var(--#{globals.$prefix}color-form-field-default); +$input-background-color-hover: var(--#{globals.$prefix}color-form-field-hover); +$input-background-color-active: var(--#{globals.$prefix}color-form-field-active); +$input-background-color-disabled: var(--#{globals.$prefix}color-disabled-background); +$input-border-color: var(--#{globals.$prefix}color-form-field-border-default); +$input-border-color-success: var(--#{globals.$prefix}color-form-field-success); +$input-border-color-warning: var(--#{globals.$prefix}color-form-field-warning); +$input-border-color-danger: var(--#{globals.$prefix}color-form-field-danger); +$input-border-color-disabled: var(--#{globals.$prefix}color-disabled-border); +$input-focus-shadow: global-tokens.$focus; +$label-color-default: var(--#{globals.$prefix}color-form-field-label); +$label-color-disabled: var(--#{globals.$prefix}color-disabled-content); +$label-required-typography: global-tokens.$body-small-regular; +$label-required-margin-left: global-tokens.$space-200; +$label-required-color: var(--#{globals.$prefix}color-form-field-danger); +$validation-text-typography: global-tokens.$body-small-semibold; +$validation-text-margin-top: global-tokens.$space-400; +$validation-text-color-disabled: var(--#{globals.$prefix}color-disabled-content); +$validation-text-color-success: var(--#{globals.$prefix}color-form-field-success); +$validation-text-color-warning: var(--#{globals.$prefix}color-form-field-warning); +$validation-text-color-danger: var(--#{globals.$prefix}color-form-field-danger); +$helper-text-typography: global-tokens.$body-small-regular; +$helper-text-margin-top: global-tokens.$space-400; +$helper-text-color-default: var(--#{globals.$prefix}color-form-field-helper-text); +$helper-text-color-disabled: var(--#{globals.$prefix}color-disabled-content); // Inline field form components – Checkbox, Radio, etc. -$inline-field-input-color-unchecked: tokens.$action-unselected-default; -$inline-field-input-color-unchecked-active: tokens.$action-unselected-active; -$inline-field-input-color-unchecked-hover: tokens.$action-unselected-hover; -$inline-field-input-color-checked: tokens.$action-selected-default; -$inline-field-input-color-checked-active: tokens.$action-selected-active; -$inline-field-input-color-checked-hover: tokens.$action-selected-hover; -$inline-field-input-outline-width: tokens.$border-width-200; +$inline-field-input-border-color-checked: var(--#{globals.$prefix}color-form-field-border-selected); +$inline-field-input-border-color-checked-disabled: var(--#{globals.$prefix}color-disabled-background); +$inline-field-input-border-width: global-tokens.$border-width-200; +$inline-field-input-background-color-checked: var(--#{globals.$prefix}color-selected-default); // Box field form components – TextField, TextArea, etc. -$box-field-input-color-default: tokens.$text-primary-default; -$box-field-input-border-width: tokens.$border-width-100; -$box-field-input-border-style: tokens.$border-style-100; -$box-field-input-border-color-default: tokens.$border-primary-default; -$box-field-input-border-color-disabled: tokens.$border-primary-disabled; -$box-field-input-border-color-focus: tokens.$focus-default; +$box-field-input-color-default: var(--#{globals.$prefix}color-form-field-content); +$box-field-input-border-width: global-tokens.$border-width-100; +$box-field-input-border-style: solid; +$box-field-input-border-color-focus: var(--#{globals.$prefix}color-border-focus); +$box-field-input-focus-shadow: global-tokens.$focus; -$box-field-input-border-radius: tokens.$radius-100; -$box-field-input-background: tokens.$background-basic; -$box-field-input-background-disabled: tokens.$background-cover; -$box-field-input-placeholder-color-default: tokens.$text-secondary-default; -$box-field-input-placeholder-color-disabled: tokens.$text-secondary-disabled; -$box-field-input-padding-x: tokens.$space-400; -$box-field-input-padding-y: calc(#{tokens.$space-400} - #{tokens.$border-width-100}); +$box-field-input-border-radius: global-tokens.$radius-300; +$box-field-input-placeholder-color-default: var(--#{globals.$prefix}color-form-field-placeholder); +$box-field-input-placeholder-color-disabled: var(--#{globals.$prefix}color-disabled-content); +$box-field-input-padding-x: global-tokens.$space-600; +$box-field-input-padding-y: calc(#{global-tokens.$space-500} - #{global-tokens.$border-width-100}); $box-field-input-width: 18rem; -$box-field-label-typography: tokens.$body-small-text-regular; -$box-field-label-margin-bottom: tokens.$space-300; +$box-field-label-typography: global-tokens.$body-small-semibold; +$box-field-label-margin-bottom: global-tokens.$space-300; $validation-states: ( success: ( @@ -68,11 +69,11 @@ $validation-states: ( ); // Item variant -$item-gap: tokens.$space-400; -$item-border-radius: tokens.$radius-100; -$item-background-color-default: tokens.$background-interactive-default; -$item-background-color-hover: tokens.$background-interactive-hover; -$item-background-color-active: tokens.$background-interactive-active; -$item-label-checked-typography: tokens.$body-medium-text-bold; -$item-validation-text-typography: tokens.$body-small-text-regular; -$item-helper-text-typography: tokens.$body-small-text-regular; +$item-gap: global-tokens.$space-500; +$item-border-radius: global-tokens.$radius-200; +$item-background-color-default: var(--#{globals.$prefix}color-background-interactive-default); +$item-background-color-hover: var(--#{globals.$prefix}color-background-interactive-hover); +$item-background-color-active: var(--#{globals.$prefix}color-background-interactive-active); +$item-label-typography: global-tokens.$body-medium-semibold; +$item-validation-text-typography: global-tokens.$body-small-semibold; +$item-helper-text-typography: global-tokens.$body-small-regular; diff --git a/packages/web/src/scss/tools/_form-fields.scss b/packages/web/src/scss/tools/_form-fields.scss index 925bc4770e..5562b883b0 100644 --- a/packages/web/src/scss/tools/_form-fields.scss +++ b/packages/web/src/scss/tools/_form-fields.scss @@ -17,6 +17,8 @@ } @mixin label-required() { + @include typography.generate(form-fields-theme.$label-required-typography); + content: '*'; margin-left: form-fields-theme.$label-required-margin-left; color: form-fields-theme.$label-required-color; @@ -33,7 +35,6 @@ display: block; margin-top: form-fields-theme.$validation-text-margin-top; list-style: none; - color: form-fields-theme.$validation-text-color-default; } @mixin validation-text-disabled() { @@ -72,14 +73,24 @@ @mixin inline-field-input() { appearance: none; - color: form-fields-theme.$inline-field-input-color-unchecked; - border: form-fields-theme.$inline-field-input-outline-width solid currentcolor; + border: form-fields-theme.$inline-field-input-border-width solid form-fields-theme.$input-border-color; + background-color: form-fields-theme.$input-background-color; cursor: cursors.$form-fields; &:focus-visible { outline: 0; box-shadow: form-fields-theme.$input-focus-shadow; } + + @media (hover: hover) { + &:hover { + background-color: form-fields-theme.$input-background-color-hover; + } + } + + &:active { + background-color: form-fields-theme.$input-background-color-active; + } } @mixin box-field-input() { @@ -206,8 +217,8 @@ @include typography.generate(form-fields-theme.$item-validation-text-typography); } -@mixin item-label-checked() { - @include typography.generate(form-fields-theme.$item-label-checked-typography); +@mixin item-label() { + @include typography.generate(form-fields-theme.$item-label-typography); } @mixin helper-text() { diff --git a/tests/e2e/demo-components-compare.spec.ts b/tests/e2e/demo-components-compare.spec.ts index 9899e6abba..1a4ad3410a 100644 --- a/tests/e2e/demo-components-compare.spec.ts +++ b/tests/e2e/demo-components-compare.spec.ts @@ -7,7 +7,6 @@ import { formatPackageName, getServerUrl, takeScreenshot, waitForPageLoad } from // Tests that are intentionally broken, but will be fixed in the future const IGNORED_TESTS: string[] = [ 'Accordion', - 'Checkbox', 'Dropdown', 'FieldGroup', 'FileUploader', diff --git a/tests/e2e/demo-components-compare.spec.ts-snapshots/checkbox-chromium-linux.png b/tests/e2e/demo-components-compare.spec.ts-snapshots/checkbox-chromium-linux.png index 1a622e326d..930c2f1436 100644 Binary files a/tests/e2e/demo-components-compare.spec.ts-snapshots/checkbox-chromium-linux.png and b/tests/e2e/demo-components-compare.spec.ts-snapshots/checkbox-chromium-linux.png differ