Skip to content

Commit

Permalink
perf(material/checkbox): Optimize more expensive selectors (#30409)
Browse files Browse the repository at this point in the history
  • Loading branch information
kseamon authored Jan 31, 2025
1 parent 00515ad commit 1b3c42e
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 17 deletions.
45 changes: 29 additions & 16 deletions src/material/checkbox/_checkbox-common.scss
Original file line number Diff line number Diff line change
Expand Up @@ -119,15 +119,17 @@ $_fallback-size: 40px;
border-color: transparent;
}

.mdc-checkbox:hover .mdc-checkbox__native-control:not(:checked) ~ .mdc-checkbox__background,
// stylelint-disable selector-combinator-space-before
.mdc-checkbox:hover > .mdc-checkbox__native-control:not(:checked) ~ .mdc-checkbox__background,
.mdc-checkbox:hover
.mdc-checkbox__native-control:not(:indeterminate) ~ .mdc-checkbox__background {
> .mdc-checkbox__native-control:not(:indeterminate) ~ .mdc-checkbox__background {
@include token-utils.create-token-slot(border-color, unselected-hover-icon-color);
background-color: transparent;
}
// stylelint-enable selector-combinator-space-before

.mdc-checkbox:hover .mdc-checkbox__native-control:checked ~ .mdc-checkbox__background,
.mdc-checkbox:hover .mdc-checkbox__native-control:indeterminate ~ .mdc-checkbox__background {
.mdc-checkbox:hover > .mdc-checkbox__native-control:checked ~ .mdc-checkbox__background,
.mdc-checkbox:hover > .mdc-checkbox__native-control:indeterminate ~ .mdc-checkbox__background {
@include token-utils.create-token-slot(border-color, selected-hover-icon-color);
@include token-utils.create-token-slot(background-color, selected-hover-icon-color);
}
Expand All @@ -147,7 +149,7 @@ $_fallback-size: 40px;

// Needs extra specificity to override the focus, hover, active states.
.mdc-checkbox--disabled.mat-mdc-checkbox-disabled-interactive {
.mdc-checkbox:hover .mdc-checkbox__native-control ~ .mdc-checkbox__background,
.mdc-checkbox:hover > .mdc-checkbox__native-control ~ .mdc-checkbox__background,
.mdc-checkbox .mdc-checkbox__native-control:focus ~ .mdc-checkbox__background,
.mdc-checkbox__background {
@include token-utils.create-token-slot(border-color, disabled-unselected-icon-color);
Expand Down Expand Up @@ -306,31 +308,31 @@ $_fallback-size: 40px;
transition: border-color $_transition-duration $_enter-curve,
background-color $_transition-duration $_enter-curve;

.mdc-checkbox__checkmark-path {
> .mdc-checkbox__checkmark > .mdc-checkbox__checkmark-path {
stroke-dashoffset: 0;
}
}

.mdc-checkbox__native-control:checked ~ .mdc-checkbox__background {
.mdc-checkbox__checkmark {
> .mdc-checkbox__checkmark {
transition: opacity $_transition-duration * 2 $_enter-curve,
transform $_transition-duration * 2 $_enter-curve;
opacity: 1;
}

.mdc-checkbox__mixedmark {
> .mdc-checkbox__mixedmark {
transform: scaleX(1) rotate(-45deg);
}
}
.mdc-checkbox__native-control:indeterminate ~ .mdc-checkbox__background {
.mdc-checkbox__checkmark {
> .mdc-checkbox__checkmark {
transform: rotate(45deg);
opacity: 0;
transition: opacity $_transition-duration $_exit-curve,
transform $_transition-duration $_exit-curve;
}

.mdc-checkbox__mixedmark {
> .mdc-checkbox__mixedmark {
transform: scaleX(1) rotate(0deg);
opacity: 1;
}
Expand Down Expand Up @@ -445,11 +447,22 @@ $_fallback-size: 40px;

// Conditionally disables the animations of the checkbox.
@mixin checkbox-noop-animations() {
&._mat-animation-noopable .mdc-checkbox {
*, *::before {
transition: none !important;
animation: none !important;
}
&._mat-animation-noopable > .mat-internal-form-field > .mdc-checkbox {
@include checkbox-noop-animations-internal;
}
}

@mixin checkbox-noop-animations-internal() {
> .mat-mdc-checkbox-touch-target,
> .mdc-checkbox__native-control,
> .mdc-checkbox__ripple,
> .mat-mdc-checkbox-ripple::before,
> .mdc-checkbox__background,
> .mdc-checkbox__background > .mdc-checkbox__checkmark,
> .mdc-checkbox__background > .mdc-checkbox__checkmark > .mdc-checkbox__checkmark-path,
> .mdc-checkbox__background > .mdc-checkbox__mixedmark {
transition: none !important;
animation: none !important;
}
}

Expand All @@ -465,7 +478,7 @@ $_fallback-size: 40px;
);
}

> .mat-mdc-checkbox-ripple .mat-ripple-element {
> .mat-mdc-checkbox-ripple > .mat-ripple-element {
@include token-utils.create-token-slot(
background-color,
unselected-hover-state-layer-color
Expand Down
6 changes: 5 additions & 1 deletion src/material/list/list-option.scss
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,14 @@
// We can't use the MDC checkbox here directly, because this checkbox is purely
// decorative and including the MDC one will bring in unnecessary JS.
@include checkbox-common.checkbox-structure(false);
@include checkbox-common.checkbox-noop-animations;
@include radio-common.radio-structure(false);
@include radio-common.radio-noop-animations;

&._mat-animation-noopable > .mdc-list-item__start > .mdc-checkbox,
&._mat-animation-noopable > .mdc-list-item__end > .mdc-checkbox {
@include checkbox-common.checkbox-noop-animations-internal;
}

// The internal checkbox/radio is purely decorative, but because it's an `input`, the user can
// still focus it by tabbing or clicking. Furthermore, `mat-list-option` has the `option` role
// which doesn't allow a nested `input`. We use `display: none` both to remove it from the tab
Expand Down

0 comments on commit 1b3c42e

Please sign in to comment.