Choices Checkbox
Installation
yarn add @chewy/kib-choices-stylesImport
@use '~@chewy/kib-choices-styles/src/kib-checkbox/styles' as kib-checkbox;Mixins
checkbox-control-state
@mixin checkbox-control-state($selection, $interaction) { ... }@mixin checkbox-control-state($selection, $interaction) { // Border/background on ::after so they stack above __fill (z-index: -1); checkmark stays on ::before. &::after { border-width: ct.get('checkbox', 'border-width', 'border'); border-style: solid; border-radius: ct.get('checkbox', 'border-radius', 'fill'); border-color: color.get('ct', 'checkbox', $selection, $interaction, 'border-color'); background-color: color.get('ct', 'checkbox', $selection, $interaction, 'fill-color'); } &::before { @supports (mask-image: url('')) or (-webkit-mask-image: url('')) { background-color: color.get('ct', 'checkbox', $selection, $interaction, 'indicator-color'); } } }
Description
Applies CT border, fill, and indicator colors on __control::after and ::before.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$selection |
| String | — none |
$interaction |
| String | — none |
Requires
- [function]
get
Used by
- [mixin]
checkbox-control
Author
CDS
-checkbox-control-checkmark
@mixin -checkbox-control-checkmark() { ... }@mixin -checkbox-control-checkmark() { content: ''; position: absolute; z-index: 2; top: 50%; left: 50%; width: settings.$checkmark-width; height: settings.$checkmark-height; transform: translate(-50%, -50%) scale(0.5); transition-property: opacity, transform; transition-duration: animation.get('press', 'scale', 'duration'); transition-timing-function: ease-out; opacity: 0; background-image: settings.$checkmark-icon; background-repeat: no-repeat; background-position: center; background-size: contain; @media (forced-colors: active) { background-image: settings.$checkmark-icon-hcm; } @supports (mask-image: url('')) or (-webkit-mask-image: url('')) { background-image: none; /* stylelint-disable plugin/use-baseline -- Progressive enhancement: mask-* tints checkmark via indicator-color */ -webkit-mask-image: settings.$checkmark-icon; mask-image: settings.$checkmark-icon; mask-repeat: no-repeat; mask-position: center; mask-size: contain; -webkit-mask-repeat: no-repeat; -webkit-mask-position: center; -webkit-mask-size: contain; @media (forced-colors: active) { background-image: settings.$checkmark-icon-hcm; } /* stylelint-enable plugin/use-baseline */ } }
Description
Base checkmark or indicator layer on __control::before (hidden until checked or mixed). SVG background-image is the baseline; mask + indicator-color tints the icon where supported.
Parameters
None.
Requires
- [function]
get - [variable]
checkmark-width - [variable]
checkmark-height - [variable]
checkmark-icon - [variable]
checkmark-icon-hcm
Used by
- [mixin]
checkbox-control
Author
CDS
checkbox-fill-state
@mixin checkbox-fill-state($selection, $interaction) { ... }@mixin checkbox-fill-state($selection, $interaction) { @include checkbox-fill-base; border-width: ct.get('checkbox', 'border-width', 'halo'); border-style: solid; border-radius: ct.get('checkbox', 'border-radius', 'bg'); border-color: color.get('ct', 'checkbox', $selection, $interaction, 'halo-color'); background-color: color.get('ct', 'checkbox', $selection, $interaction, 'bg-color'); }
Description
CT halo and background tokens for the __fill element.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$selection |
| String | — none |
$interaction |
| String | — none |
Requires
- [mixin]
checkbox-fill-base - [function]
get
Used by
- [mixin]
checkbox-fill
Author
CDS
checkbox-field
@mixin checkbox-field($block) { ... }@mixin checkbox-field($block) { display: flex; position: relative; flex-wrap: nowrap; align-items: flex-start; &:has(#{$block}__native:disabled) { opacity: 0.5; @media (forced-colors: active) { opacity: 1; } } }
Description
Field wrapper layout and disabled opacity for the checkbox block.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$block | Root BEM block class (default | String | — none |
Author
CDS
checkbox-label-state
@mixin checkbox-label-state($block) { ... }@mixin checkbox-label-state($block) { $label-active: ( 'unselected': ':not(:checked):not(:indeterminate)', 'selected': ':checked', 'mixed': ':indeterminate' ); $label-hover: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); $label-focus: ( 'unselected': ':focus-visible:not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:focus-visible:not(:disabled)', 'mixed': ':indeterminate:focus-visible:not(:disabled)' ); $label-pressed: ( 'unselected': ':not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:disabled)', 'mixed': ':indeterminate:not(:disabled)' ); $label-error: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); font-family: typography.get('text-typeface'); font-size: typography.get('fs-product-text-2'); font-weight: typography.get-weight('product-text-weight-normal'); line-height: typography.get('lh-product-text-2'); letter-spacing: typography.get('ls-standard'); margin-left: spacing.get('s2'); color: color.get('text', 'primary'); cursor: pointer; #{$block}__native:disabled ~ & { color: color.get('text', 'tertiary'); pointer-events: none; } @each $selection, $native-suffix in $label-active { #{$block}__native#{$native-suffix} ~ & { color: color.get('ct', 'checkbox', $selection, 'active', 'text-primary-color'); } } @each $selection, $native-suffix in $label-hover { #{$block}__field:hover:has(#{$block}__native#{$native-suffix}) & { color: color.get('ct', 'checkbox', $selection, 'hover', 'text-primary-color'); } } @each $selection, $native-suffix in $label-focus { #{$block}__native#{$native-suffix}:focus-visible ~ & { color: color.get('ct', 'checkbox', $selection, 'focus', 'text-primary-color'); } } @each $selection, $native-suffix in $label-pressed { #{$block}__native#{$native-suffix}:active ~ & { color: color.get('ct', 'checkbox', $selection, 'pressed', 'text-primary-color'); } #{$block}__field:has(#{$block}__native#{$native-suffix}:active) &, #{$block}__field:has(#{$block}__label:active):has(#{$block}__native#{$native-suffix}) & { color: color.get('ct', 'checkbox', $selection, 'pressed', 'text-primary-color'); } } @each $selection, $native-suffix in $label-error { #{$block}__field--invalid:has(#{$block}__native#{$native-suffix}) & { color: color.get('ct', 'checkbox', $selection, 'error', 'text-primary-color'); } } }
Description
Label typography and CT text colors for native selection and interaction states.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$block | Root BEM block class (default | String | — none |
Requires
- [function]
get - [function]
get-weight
Author
CDS
-checkbox-fill-forced-colors
@mixin -checkbox-fill-forced-colors() { ... }@mixin -checkbox-fill-forced-colors() { @media (forced-colors: active) { border-color: Highlight; background-color: Highlight; } }
Description
Forced-colors highlight on __fill for checked and indeterminate states.
Parameters
None.
Used by
- [mixin]
checkbox-fill-checked - [mixin]
checkbox-fill-mixed
Author
CDS
checkbox-fill-checked
@mixin checkbox-fill-checked() { ... }@mixin checkbox-fill-checked() { @include -checkbox-fill-forced-colors; &::before { transform: translate(-50%, -50%) scale(0); opacity: 0; } &::after { transform: translate(-50%, -50%) scale(1); opacity: 1; color: HighlightText; } }
Description
__fill pseudo-element animation targets when the native input is checked.
Parameters
None.
Requires
- [mixin]
-checkbox-fill-forced-colors
Used by
- [mixin]
checkbox-control
Author
CDS
checkbox-fill-mixed
@mixin checkbox-fill-mixed() { ... }@mixin checkbox-fill-mixed() { @include -checkbox-fill-forced-colors; &::before { transform: translate(-50%, -50%) scale(1); opacity: 1; } &::after { transform: translate(-50%, -50%) scale(0.75); opacity: 0; } @media (forced-colors: active) { color: HighlightText; } }
Description
__fill pseudo-element animation targets when the native input is indeterminate.
Parameters
None.
Requires
- [mixin]
-checkbox-fill-forced-colors
Used by
- [mixin]
checkbox-control
Author
CDS
checkbox-control-custom-base
@mixin checkbox-control-custom-base() { ... }@mixin checkbox-control-custom-base() { display: block; isolation: isolate; position: relative; flex-shrink: 0; width: settings.$control-size; height: settings.$control-size; pointer-events: none; &::after { content: ''; position: absolute; z-index: 1; inset: 0; border-radius: ct.get('checkbox', 'border-radius', 'fill'); pointer-events: none; } }
Description
Size and ::after shell for the custom control (checkmark on ::before).
Parameters
None.
Requires
- [function]
get - [variable]
control-size
Used by
- [mixin]
checkbox-control
Author
CDS
-checkbox-control-forced-colors
@mixin -checkbox-control-forced-colors() { ... }@mixin -checkbox-control-forced-colors() { @media (forced-colors: active) { &::after { border-color: CanvasText; background-color: Canvas; } #{$block}__native:checked:not(:disabled) ~ &, #{$block}__native:indeterminate:not(:disabled) ~ & { &::after { border-color: Highlight; background-color: Highlight; } } #{$block}__native:disabled ~ & { &::after { border-color: GrayText; background-color: Canvas; } } @media (hover: hover) and (pointer: fine) { @if $hover-scope { #{$block}__#{$hover-scope}:hover:has( #{$block}__native:not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate) ) & { &::after { border-color: Highlight; background-color: Canvas; } } #{$block}__#{$hover-scope}:hover:has( #{$block}__native:checked:not(:focus-visible):not(:disabled) ) &, #{$block}__#{$hover-scope}:hover:has( #{$block}__native:indeterminate:not(:focus-visible):not(:disabled) ) & { &::after { border-color: Highlight; background-color: Highlight; } } } @else { #{$block}:hover:has( #{$block}__native:not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate) ) & { &::after { border-color: Highlight; background-color: Canvas; } } #{$block}:hover:has(#{$block}__native:checked:not(:focus-visible):not(:disabled)) &, #{$block}:hover:has(#{$block}__native:indeterminate:not(:focus-visible):not(:disabled)) & { &::after { border-color: Highlight; background-color: Highlight; } } } } } }
Description
Forced-colors styles for the custom control surface (::after).
Parameters
None.
Used by
- [mixin]
checkbox-control
Author
CDS
checkbox-control
@mixin checkbox-control($block, $fill-element, $hover-scope) { ... }@mixin checkbox-control($block, $fill-element, $hover-scope) { $control-active: ( 'unselected': ':not(:checked):not(:indeterminate)', 'selected': ':checked', 'mixed': ':indeterminate' ); $control-hover: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); $control-focus: ( 'unselected': ':focus-visible:not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:focus-visible:not(:disabled)', 'mixed': ':indeterminate:focus-visible:not(:disabled)' ); $control-pressed: ( 'unselected': ':not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:disabled)', 'mixed': ':indeterminate:not(:disabled)' ); $control-error: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); @include checkbox-control-custom-base; // Checkmark on ::before; control surface (border/background) on ::after above __fill. &::before { @include -checkbox-control-checkmark; } #{$block}__native:checked ~ & { @include checkbox-control-state('selected', 'active'); &::before { transform: translate(-50%, -50%) scale(1); opacity: 1; } #{$block}__#{$fill-element} { @include checkbox-fill-checked; } } #{$block}__native:indeterminate ~ & { @include checkbox-control-state('mixed', 'active'); &::before { content: ''; width: 60%; height: 10%; transform: translate(-50%, -50%); opacity: 1; // Solid dash for mixed state (fallback). Checked uses background-image; mask browsers need color + no mask. background-color: color.get('ct', 'checkbox', 'mixed', 'active', 'indicator-color'); background-image: none; // Clear checkmark mask from -checkbox-control-checkmark (only emitted inside @supports there). /* stylelint-disable plugin/use-baseline -- Override checkmark mask so mixed dash renders as a filled bar */ -webkit-mask-image: none; mask-image: none; mask-repeat: unset; mask-position: unset; mask-size: unset; /* stylelint-enable plugin/use-baseline */ @media (forced-colors: active) { background-color: CanvasText; background-image: none; } } #{$block}__#{$fill-element} { @include checkbox-fill-mixed; } } @each $selection, $native-suffix in $control-active { #{$block}__native#{$native-suffix} ~ & { @include checkbox-control-state($selection, 'active'); } } @each $selection, $native-suffix in $control-hover { @if $hover-scope { #{$block}__#{$hover-scope}:hover:has(#{$block}__native#{$native-suffix}) & { @include checkbox-control-state($selection, 'hover'); } } @else { #{$block}:hover:has(#{$block}__native#{$native-suffix}) & { @include checkbox-control-state($selection, 'hover'); } } } @each $selection, $native-suffix in $control-focus { #{$block}__native#{$native-suffix} ~ & { @include checkbox-control-state($selection, 'focus'); } } @each $selection, $native-suffix in $control-pressed { #{$block}__native:active#{$native-suffix} ~ & { @include checkbox-control-state($selection, 'pressed'); } @if $hover-scope { #{$block}__#{$hover-scope}:has(#{$block}__native#{$native-suffix}:active) &, #{$block}__#{$hover-scope}:has(#{$block}__label:active):has( #{$block}__native#{$native-suffix} ) & { @include checkbox-control-state($selection, 'pressed'); } } @else { #{$block}:has(#{$block}__native#{$native-suffix}:active) &, #{$block}:has(#{$block}__label:active):has(#{$block}__native#{$native-suffix}) & { @include checkbox-control-state($selection, 'pressed'); } } } @each $selection, $native-suffix in $control-error { #{$block}__field--invalid:has(#{$block}__native#{$native-suffix}) & { @include checkbox-control-state($selection, 'error'); } } @include -checkbox-control-forced-colors($block, $hover-scope); }
Description
Custom control surface, checkmark or dash indicator, and CT state wiring.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$block | Root BEM block class (default | String | — none |
$fill-element | BEM element for the halo node (default | String | — none |
$hover-scope | Hover host element (default | String or False | — none |
Requires
- [mixin]
checkbox-control-custom-base - [mixin]
-checkbox-control-checkmark - [mixin]
checkbox-control-state - [mixin]
checkbox-fill-checked - [mixin]
checkbox-fill-mixed - [mixin]
-checkbox-control-forced-colors - [function]
get
Author
CDS
checkbox-fill-base
@mixin checkbox-fill-base() { ... }@mixin checkbox-fill-base() { position: absolute; z-index: -1; top: 50%; left: 50%; width: settings.$fill-size; height: settings.$fill-size; overflow: hidden; transform: translate(-50%, -50%); }
Description
Centers the halo __fill behind the control.
Parameters
None.
Requires
- [variable]
fill-size
Used by
- [mixin]
checkbox-fill-state
Author
CDS
-checkbox-fill-forced-colors-override
@mixin -checkbox-fill-forced-colors-override() { ... }@mixin -checkbox-fill-forced-colors-override() { @media (forced-colors: active) { #{$block}__native:checked:not(:disabled) ~ #{$block}__#{$control-element} &, #{$block}__native:indeterminate:not(:disabled) ~ #{$block}__#{$control-element} & { border-color: Highlight; background-color: Highlight; } @media (hover: hover) and (pointer: fine) { @if $hover-scope { #{$block}__#{$hover-scope}:hover:has( #{$block}__native:not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate) ) ~ #{$block}__#{$control-element} & { border-color: Highlight; background-color: Canvas; } #{$block}__#{$hover-scope}:hover:has( #{$block}__native:checked:not(:focus-visible):not(:disabled) ) ~ #{$block}__#{$control-element} &, #{$block}__#{$hover-scope}:hover:has( #{$block}__native:indeterminate:not(:focus-visible):not(:disabled) ) ~ #{$block}__#{$control-element} & { border-color: Highlight; background-color: Highlight; } } @else { #{$block}:hover:has( #{$block}__native:not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate) ) ~ #{$block}__#{$control-element} & { border-color: Highlight; background-color: Canvas; } #{$block}:hover:has(#{$block}__native:checked:not(:focus-visible):not(:disabled)) ~ #{$block}__#{$control-element} &, #{$block}:hover:has(#{$block}__native:indeterminate:not(:focus-visible):not(:disabled)) ~ #{$block}__#{$control-element} & { border-color: Highlight; background-color: Highlight; } } } } }
Description
Forced-colors override for __fill so system colors win over token state rules.
Parameters
None.
Used by
- [mixin]
checkbox-fill
Author
CDS
checkbox-fill
@mixin checkbox-fill($block, $control-element, $hover-scope) { ... }@mixin checkbox-fill($block, $control-element, $hover-scope) { $fill-active: ( 'unselected': ':not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible)', 'mixed': ':indeterminate:not(:focus-visible)' ); $fill-hover: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); $fill-focus: ( 'unselected': ':focus-visible:not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:focus-visible:not(:disabled)', 'mixed': ':indeterminate:focus-visible:not(:disabled)' ); $fill-pressed: ( 'unselected': ':not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:disabled)', 'mixed': ':indeterminate:not(:disabled)' ); $fill-error: ( 'unselected': ':not(:focus-visible):not(:disabled):not(:checked):not(:indeterminate)', 'selected': ':checked:not(:focus-visible):not(:disabled)', 'mixed': ':indeterminate:not(:focus-visible):not(:disabled)' ); @each $selection, $native-suffix in $fill-active { #{$block}__native#{$native-suffix} ~ #{$block}__#{$control-element} & { @include checkbox-fill-state($selection, 'active'); } } @each $selection, $native-suffix in $fill-focus { #{$block}__native#{$native-suffix} ~ #{$block}__#{$control-element} & { @include checkbox-fill-state($selection, 'focus'); } } @each $selection, $native-suffix in $fill-hover { @if $hover-scope { #{$block}__#{$hover-scope}:hover:has(#{$block}__native#{$native-suffix}) & { @include checkbox-fill-state($selection, 'hover'); } } @else { #{$block}:hover:has(#{$block}__native#{$native-suffix}) & { @include checkbox-fill-state($selection, 'hover'); } } } @each $selection, $native-suffix in $fill-pressed { #{$block}__native:active#{$native-suffix} ~ #{$block}__#{$control-element} & { @include checkbox-fill-state($selection, 'pressed'); } @if $hover-scope { #{$block}__#{$hover-scope}:has(#{$block}__native#{$native-suffix}:active) &, #{$block}__#{$hover-scope}:has(#{$block}__label:active):has( #{$block}__native#{$native-suffix} ) & { @include checkbox-fill-state($selection, 'pressed'); } } @else { #{$block}:has(#{$block}__native#{$native-suffix}:active) &, #{$block}:has(#{$block}__label:active):has(#{$block}__native#{$native-suffix}) & { @include checkbox-fill-state($selection, 'pressed'); } } } @each $selection, $native-suffix in $fill-error { #{$block}__field--invalid:has(#{$block}__native#{$native-suffix}) & { @include checkbox-fill-state($selection, 'error'); } } @include -checkbox-fill-forced-colors-override($block, $control-element, $hover-scope); }
Description
Halo __fill CT tokens for native selection and interaction states.
Parameters
| parameter Name | parameter Description | parameter Type | parameter Default value |
|---|---|---|---|
$block | Root BEM block class (default | String | — none |
$control-element | BEM element for the control node (default | String | — none |
$hover-scope | Hover host element (default | String or False | — none |
Requires
- [mixin]
checkbox-fill-state - [mixin]
-checkbox-fill-forced-colors-override
Author
CDS
Variables
control-size
$control-size: calc(#{typography.get('fs-utility-4')} * #{typography.get('lh-utility-4')}) !default;Description
Control width and height. Sized from the utility-4 line box (fs-utility-4 × lh-utility-4 = 20px in the base theme) so the control scales with theme typography tokens.
Type
String
Author
CDS
fill-size
$fill-size: calc(#{typography.get('fs-utility-5')} * #{typography.get('lh-utility-5')}) !default;Description
Fill (halo) width and height. Sized from the utility-5 line box (fs-utility-5 × lh-utility-5 = 24px in the base theme).
Type
String
Used by
- [mixin]
checkbox-fill-base
Author
CDS
checkmark-width
$checkmark-width: 75% !default;Description
Checkmark icon width as a percentage of the control size
Type
Number
Used by
- [mixin]
-checkbox-control-checkmark
Author
CDS
checkmark-height
$checkmark-height: 75% !default;Description
Checkmark icon height as a percentage of the control size
Type
Number
Used by
- [mixin]
-checkbox-control-checkmark
Author
CDS
checkmark-icon
$checkmark-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 15 11'%3E%3Cpath fill='%23fff' d='M4.5 8.5L1.58 5.58a.82.82 0 00-1.16 0 .82.82 0 000 1.17l3.49 3.5c.32.32.85.32 1.17 0l8.84-8.83a.82.82 0 000-1.17.82.82 0 00-1.17 0L4.5 8.5z'/%3E%3C/svg%3E") !default;Description
Checkmark SVG icon (standard mode)
Type
String
Used by
- [mixin]
-checkbox-control-checkmark
Author
CDS
checkmark-icon-hcm
$checkmark-icon-hcm: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 15 11'%3E%3Cpath fill='HighlightText' d='M4.5 8.5L1.58 5.58a.82.82 0 00-1.16 0 .82.82 0 000 1.17l3.49 3.5c.32.32.85.32 1.17 0l8.84-8.83a.82.82 0 000-1.17.82.82 0 00-1.17 0L4.5 8.5z'/%3E%3C/svg%3E") !default;Description
Checkmark SVG icon (high-contrast mode)
Type
String
Used by
- [mixin]
-checkbox-control-checkmark
Author
CDS