/
githubmirror
/
components
Обзор
Документация
Войти
/
githubmirror
/
components
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/material/button/_button-base.scss
182 строки
6 KB
Andrew Seguin
fix(multiple): use focus-visible for focus indicator (#32514)
10 дек 2025, 23:59
Не верифицирован
10 дек 2025, 23:59
d4e104a
Код
Авторство
О чём код?
@use '../core/tokens/token-utils'; @use '../core/style/layout-common'; // Adds styles necessary to provide stateful interactions with the button. This includes providing // content for the state container's ::before and ::after so that they can be given a background // color and opacity for states like hover, active, and focus. Additionally, adds styles to the // ripple and state container so that they fill the button, match the border radius, and avoid // pointer events. @mixin mat-private-button-interactive($focus-indicator-inherits-shape: true) { -webkit-tap-highlight-color: transparent; // The ripple container should match the bounds of the entire button. .mat-mdc-button-ripple, .mat-mdc-button-persistent-ripple, .mat-mdc-button-persistent-ripple::before { @include layout-common.fill; // Disable pointer events for the ripple container and state overlay because the container // will overlay the user content and we don't want to disable mouse events on the user content. // Pointer events can be safely disabled because the ripple trigger element is the host element. pointer-events: none; // Inherit the border radius from the parent so that state overlay and ripples don't exceed the // parent button boundaries. Note that an inherited border radius does not work properly if // the actual button element does have a border because it causes the inner content to be // smaller. We have special logic for stroked buttons to handle this scenario. border-radius: inherit; } // This style used to be applied by the MatRipple // directive, which is no longer attached to this element. .mat-mdc-button-ripple { overflow: hidden; } // We use ::before so that we can reuse some of MDC's theming. .mat-mdc-button-persistent-ripple::before { content: ''; opacity: 0; } // The content should appear over the state and ripple layers, otherwise they may adversely affect // the accessibility of the text content. .mdc-button__label, .mat-icon { z-index: 1; position: relative; } // The focus indicator should match the bounds of the entire button. .mat-focus-indicator { @include layout-common.fill(); @if ($focus-indicator-inherits-shape) { border-radius: inherit; } } &:focus-visible > .mat-focus-indicator::before { content: ''; @if ($focus-indicator-inherits-shape) { border-radius: inherit; } } } @mixin mat-private-button-ripple( $ripple-color-token, $state-layer-color-token, $disabled-state-layer-color-token, $hover-state-layer-opacity-token, $focus-state-layer-opacity-token, $pressed-state-layer-opacity-token, $fallbacks ) { .mat-ripple-element { background-color: token-utils.slot($ripple-color-token, $fallbacks); } .mat-mdc-button-persistent-ripple::before { background-color: token-utils.slot($state-layer-color-token, $fallbacks); } &.mat-mdc-button-disabled .mat-mdc-button-persistent-ripple::before { background-color: token-utils.slot($disabled-state-layer-color-token, $fallbacks); } &:hover > .mat-mdc-button-persistent-ripple::before { opacity: token-utils.slot($hover-state-layer-opacity-token, $fallbacks); } &.cdk-program-focused, &.cdk-keyboard-focused, &.mat-mdc-button-disabled-interactive:focus { > .mat-mdc-button-persistent-ripple::before { opacity: token-utils.slot($focus-state-layer-opacity-token, $fallbacks); } } &:active > .mat-mdc-button-persistent-ripple::before { opacity: token-utils.slot($pressed-state-layer-opacity-token, $fallbacks); } } // MDC's disabled buttons define a default cursor with pointer-events none. However, they select // :disabled for this, which does not affect anchor tags. // TODO(andrewseguin): Discuss with the MDC team about a mixin we can call for applying this style, // and note that having pointer-events may have unintended side-effects, e.g. allowing the user // to click the target underneath the button. @mixin mat-private-button-disabled() { // `[disabled]` shouldn't be necessary, but we keep it to maintain // compatibility with apps setting it through host bindings. &[disabled], &.mat-mdc-button-disabled { cursor: default; pointer-events: none; @content; } &.mat-mdc-button-disabled-interactive { pointer-events: auto; } } @mixin mat-private-button-touch-target( $is-square, $touch-target-size-token, $touch-target-display-token, $fallbacks) { .mat-mdc-button-touch-target { position: absolute; top: 50%; height: token-utils.slot($touch-target-size-token, $fallbacks); display: token-utils.slot($touch-target-display-token, $fallbacks); @if $is-square { left: 50%; width: token-utils.slot($touch-target-size-token, $fallbacks); transform: translate(-50%, -50%); } @else { left: 0; right: 0; transform: translateY(-50%); } } } @mixin mat-private-button-horizontal-layout( $icon-spacing-token, $icon-offset-token, $with-icon-horizontal-padding-token, $fallbacks) { $icon-spacing: token-utils.slot($icon-spacing-token, $fallbacks, true); $icon-offset: token-utils.slot($icon-offset-token, $fallbacks, true); @if ($with-icon-horizontal-padding-token) { // stylelint-disable-next-line selector-class-pattern &:has(.material-icons, mat-icon, [matButtonIcon]) { padding: 0 token-utils.slot($with-icon-horizontal-padding-token, $fallbacks, true); } } // MDC expects button icons to contain this HTML content: // ```html // <span class="mdc-button__icon material-icons">favorite</span> // ``` // However, Angular Material expects a `mat-icon` instead. The following // styles will lay out the icons appropriately. & > .mat-icon { margin-right: $icon-spacing; margin-left: $icon-offset; [dir='rtl'] & { margin-right: $icon-offset; margin-left: $icon-spacing; } } .mdc-button__label + .mat-icon { margin-right: $icon-offset; margin-left: $icon-spacing; [dir='rtl'] & { margin-right: $icon-spacing; margin-left: $icon-offset; } } }