/
githubmirror
/
components
Обзор
Документация
Войти
/
githubmirror
/
components
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/material/radio/_radio-common.scss
278 строк
8 KB
Kristiyan Kostadinov
fix(material/radio): do not set cursor on non interactive radio (#33418)
18 июн 2026, 19:46
Не верифицирован
18 июн 2026, 19:46
d81320f
Код
Авторство
О чём код?
@use '@angular/cdk'; @use './m3-radio'; @use '../core/tokens/token-utils'; $_icon-size: 20px; $fallbacks: m3-radio.get-tokens(); @function _enter-transition($name) { @return $name 90ms cubic-bezier(0, 0, 0.2, 1); } @function _exit-transition($name) { @return $name 90ms cubic-bezier(0.4, 0, 0.6, 1); } // Structural styles for a radio button. Shared with the selection list. @mixin radio-structure($is-interactive) { .mdc-radio { display: inline-block; position: relative; flex: 0 0 auto; box-sizing: content-box; width: $_icon-size; height: $_icon-size; // This is something we inherited from MDC, but it shouldn't be necessary. // Removing it will likely lead to screenshot diffs. will-change: opacity, transform, border-color, color; $size-token: token-utils.slot(radio-state-layer-size, $fallbacks); padding: calc((#{$size-token} - #{$_icon-size}) / 2); @if ($is-interactive) { cursor: pointer; // MDC's hover indication comes from their ripple which we don't use. &:hover > .mdc-radio__native-control:not([disabled]):not(:focus) { & ~ .mdc-radio__background::before { opacity: 0.04; transform: scale(1); } } &:hover > .mdc-radio__native-control:not([disabled]) ~ .mdc-radio__background { > .mdc-radio__outer-circle { border-color: token-utils.slot(radio-unselected-hover-icon-color, $fallbacks); } } &:hover > .mdc-radio__native-control:enabled:checked + .mdc-radio__background { $token: 'radio-selected-hover-icon-color'; > .mdc-radio__outer-circle { border-color: token-utils.slot($token, $fallbacks); } > .mdc-radio__inner-circle { background-color: token-utils.slot($token, $fallbacks, currentColor); } } &:active > .mdc-radio__native-control:enabled:not(:checked) + .mdc-radio__background { > .mdc-radio__outer-circle { border-color: token-utils.slot(radio-unselected-pressed-icon-color, $fallbacks); } } &:active > .mdc-radio__native-control:enabled:checked + .mdc-radio__background { $token: 'radio-selected-pressed-icon-color'; > .mdc-radio__outer-circle { border-color: token-utils.slot($token, $fallbacks); } > .mdc-radio__inner-circle { background-color: token-utils.slot($token, $fallbacks, currentColor); } } } } .mdc-radio__background { display: inline-block; position: relative; box-sizing: border-box; width: $_icon-size; height: $_icon-size; &::before { position: absolute; transform: scale(0, 0); border-radius: 50%; opacity: 0; pointer-events: none; content: ''; transition: _exit-transition(opacity), _exit-transition(transform); $size: token-utils.slot(radio-state-layer-size, $fallbacks); $offset: calc(-1 * (#{$size} - #{$_icon-size}) / 2); width: $size; height: $size; top: $offset; left: $offset; } } .mdc-radio__outer-circle { position: absolute; top: 0; left: 0; box-sizing: border-box; width: 100%; height: 100%; border-width: 2px; border-style: solid; border-radius: 50%; transition: _exit-transition(border-color); } .mdc-radio__inner-circle { position: absolute; top: 0; left: 0; box-sizing: border-box; width: 100%; height: 100%; transform: scale(0); border-radius: 50%; transition: _exit-transition(transform), _exit-transition(background-color); @include cdk.high-contrast { // Override the color, because solid colors don't show up by default in // high contrast mode. We need !important here, because the various state // selectors are really specific and duplicating them will be brittle. background-color: CanvasText !important; } } .mdc-radio__native-control { position: absolute; margin: 0; padding: 0; opacity: 0; top: 0; right: 0; left: 0; cursor: inherit; z-index: 1; width: token-utils.slot(radio-state-layer-size, $fallbacks); height: token-utils.slot(radio-state-layer-size, $fallbacks); &:checked, &:disabled { + .mdc-radio__background { transition: _enter-transition(opacity), _enter-transition(transform); > .mdc-radio__outer-circle { transition: _enter-transition(border-color); } > .mdc-radio__inner-circle { transition: _enter-transition(transform), _enter-transition(background-color); } } } @if ($is-interactive) { &:focus + .mdc-radio__background::before { transform: scale(1); opacity: 0.12; transition: _enter-transition(opacity), _enter-transition(transform); } } &:disabled { &:not(:checked) + .mdc-radio__background > .mdc-radio__outer-circle { border-color: token-utils.slot(radio-disabled-unselected-icon-color, $fallbacks); opacity: token-utils.slot(radio-disabled-unselected-icon-opacity, $fallbacks); } + .mdc-radio__background { $color-token: 'radio-disabled-selected-icon-color'; $opacity-token: token-utils.slot(radio-disabled-selected-icon-opacity, $fallbacks); cursor: default; > .mdc-radio__outer-circle { border-color: token-utils.slot($color-token, $fallbacks); opacity: $opacity-token; } > .mdc-radio__inner-circle { background-color: token-utils.slot($color-token, $fallbacks, currentColor); opacity: $opacity-token; } } } &:enabled { &:not(:checked) + .mdc-radio__background > .mdc-radio__outer-circle { border-color: token-utils.slot(radio-unselected-icon-color, $fallbacks); } &:checked + .mdc-radio__background { $token: 'radio-selected-icon-color'; > .mdc-radio__outer-circle { border-color: token-utils.slot($token, $fallbacks); } > .mdc-radio__inner-circle { background-color: token-utils.slot($token, $fallbacks, currentColor); } } @if ($is-interactive) { &:focus:checked + .mdc-radio__background { $token: 'radio-selected-focus-icon-color'; > .mdc-radio__outer-circle { border-color: token-utils.slot($token, $fallbacks); } > .mdc-radio__inner-circle { background-color: token-utils.slot($token, $fallbacks, currentColor); } } } } &:checked + .mdc-radio__background > .mdc-radio__inner-circle { transform: scale(0.5); transition: _enter-transition(transform), _enter-transition(background-color); } } @if ($is-interactive) { &.mat-mdc-radio-disabled-interactive .mdc-radio--disabled { pointer-events: auto; // stylelint-disable selector-combinator-space-before .mdc-radio__native-control:not(:checked) + .mdc-radio__background > .mdc-radio__outer-circle { border-color: token-utils.slot(radio-disabled-unselected-icon-color, $fallbacks); opacity: token-utils.slot(radio-disabled-unselected-icon-opacity, $fallbacks); } // stylelint-enable selector-combinator-space-before &:hover .mdc-radio__native-control:checked + .mdc-radio__background, .mdc-radio__native-control:checked:focus + .mdc-radio__background, .mdc-radio__native-control + .mdc-radio__background { $color-token: 'radio-disabled-selected-icon-color'; $opacity-token: token-utils.slot(radio-disabled-selected-icon-opacity, $fallbacks); > .mdc-radio__outer-circle { border-color: token-utils.slot($color-token, $fallbacks); opacity: $opacity-token; } > .mdc-radio__inner-circle { background-color: token-utils.slot($color-token, $fallbacks, currentColor); opacity: $opacity-token; } } } } } // Conditionally disables the animations of the radio button. @mixin radio-noop-animations() { &._mat-animation-noopable { .mdc-radio__background::before, .mdc-radio__outer-circle, .mdc-radio__inner-circle { // Needs to be `!important`, because MDC's selectors are really specific. transition: none !important; } } }