diff --git a/src/material/slide-toggle/slide-toggle.scss b/src/material/slide-toggle/slide-toggle.scss index 2ee4027d2520..ac7f641b9aba 100644 --- a/src/material/slide-toggle/slide-toggle.scss +++ b/src/material/slide-toggle/slide-toggle.scss @@ -3,6 +3,7 @@ @use '../core/tokens/m2/mat/switch' as tokens-mat-switch; @use '../core/tokens/m2/mdc/switch' as tokens-mdc-switch; @use '../core/tokens/token-utils'; +@use '../core/style/vendor-prefixes'; $_mdc-slots: (tokens-mdc-switch.$prefix, tokens-mdc-switch.get-token-slots()); $_mat-slots: (tokens-mat-switch.$prefix, tokens-mat-switch.get-token-slots()); @@ -12,7 +13,6 @@ $_interactive-disabled-selector: '.mat-mdc-slide-toggle-disabled-interactive.mdc align-items: center; background: none; border: none; - cursor: pointer; display: inline-flex; flex-shrink: 0; margin: 0; @@ -21,15 +21,6 @@ $_interactive-disabled-selector: '.mat-mdc-slide-toggle-disabled-interactive.mdc padding: 0; position: relative; - &.mdc-switch--disabled { - cursor: default; - pointer-events: none; - } - - &.mat-mdc-slide-toggle-disabled-interactive { - pointer-events: auto; - } - @include token-utils.use-tokens($_mdc-slots...) { @include token-utils.create-token-slot(width, track-width); } @@ -503,8 +494,23 @@ $_interactive-disabled-selector: '.mat-mdc-slide-toggle-disabled-interactive.mdc } .mat-mdc-slide-toggle { + @include vendor-prefixes.user-select(none); display: inline-block; -webkit-tap-highlight-color: transparent; + cursor: pointer; + + &:has(.mdc-switch--disabled) { + pointer-events: none; + cursor: auto; + } + + &:has(.mat-mdc-slide-toggle-disabled-interactive) { + pointer-events: auto; + } + + button, label { + cursor: inherit; + } // Remove the native outline since we use the ripple for focus indication. outline: 0; @@ -564,11 +570,6 @@ $_interactive-disabled-selector: '.mat-mdc-slide-toggle-disabled-interactive.mdc } } - // If our slide-toggle is enabled the cursor on label should appear as a pointer. - .mdc-switch:enabled + .mdc-label { - cursor: pointer; - } - // TODO(wagnermaciel): Use our custom token system to emit this css rule. .mdc-switch--disabled + label { color: var(--mdc-switch-disabled-label-text-color); diff --git a/src/material/slide-toggle/slide-toggle.ts b/src/material/slide-toggle/slide-toggle.ts index 28837bcf85c9..117c35055d4a 100644 --- a/src/material/slide-toggle/slide-toggle.ts +++ b/src/material/slide-toggle/slide-toggle.ts @@ -82,6 +82,7 @@ let nextUniqueId = 0; '[class.mat-mdc-slide-toggle-checked]': 'checked', '[class._mat-animation-noopable]': '_noopAnimations', '[class]': 'color ? "mat-" + color : ""', + '(click)': '_handleHostClick($event)', }, exportAs: 'matSlideToggle', encapsulation: ViewEncapsulation.None, @@ -319,4 +320,12 @@ export class MatSlideToggle // `aria-labelledby`, because the button gets flagged as not having a label by tools like axe. return this.ariaLabel ? null : this._labelId; } + + protected _handleHostClick(event: MouseEvent) { + // Treat any clicks on the container as clicks on the button element. + const switchEl = this._switchElement?.nativeElement; + if (switchEl && !switchEl.contains(event.target as HTMLElement)) { + this._handleClick(); + } + } } diff --git a/tools/public_api_guard/material/slide-toggle.md b/tools/public_api_guard/material/slide-toggle.md index 1e14c8840e4a..c14d696f7fe0 100644 --- a/tools/public_api_guard/material/slide-toggle.md +++ b/tools/public_api_guard/material/slide-toggle.md @@ -63,6 +63,8 @@ export class MatSlideToggle implements OnDestroy, AfterContentInit, OnChanges, C // (undocumented) _getAriaLabelledBy(): string | null; _handleClick(): void; + // (undocumented) + protected _handleHostClick(event: MouseEvent): void; hideIcon: boolean; id: string; get inputId(): string;