Skip to content

Commit 6074fd1

Browse files
crisbetommalerba
authored andcommitted
fix(material-experimental/mdc-radio): add accessible touch targets (#22994)
Sets up accessible touch targets on the MDC-based radio button. Also hides the touch targets on the two lowest densities. This is something I forgot to do in #22892. Fixes #22991. (cherry picked from commit 150d5af)
1 parent 539e4cd commit 6074fd1

File tree

7 files changed

+42
-15
lines changed

7 files changed

+42
-15
lines changed

src/material-experimental/mdc-checkbox/_checkbox-theme.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,12 @@
125125
$query: mdc-helpers.$mat-base-styles-query
126126
);
127127
}
128+
129+
@if ($density-scale == -2 or $density-scale == 'minimum') {
130+
.mat-mdc-checkbox-touch-target {
131+
display: none;
132+
}
133+
}
128134
}
129135

130136
@mixin theme($theme-or-color-config) {

src/material-experimental/mdc-radio/_radio-theme.scss

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@
5858
.mat-mdc-radio-button .mdc-radio {
5959
@include mdc-radio-theme.density($density-scale, $query: mdc-helpers.$mat-base-styles-query);
6060
}
61+
62+
@if ($density-scale == -2 or $density-scale == 'minimum') {
63+
.mat-mdc-radio-touch-target {
64+
display: none;
65+
}
66+
}
6167
}
6268

6369
@mixin theme($theme-or-color-config) {

src/material-experimental/mdc-radio/radio.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
<div class="mdc-form-field" #formField
22
[class.mdc-form-field--align-end]="labelPosition == 'before'">
33
<div class="mdc-radio" [ngClass]="_classes">
4+
<!-- Render this element first so the input is on top. -->
5+
<div class="mat-mdc-radio-touch-target" (click)="_onInputInteraction($event)"></div>
46
<input #input class="mdc-radio__native-control" type="radio"
57
[id]="inputId"
68
[checked]="checked"
@@ -12,7 +14,7 @@
1214
[attr.aria-label]="ariaLabel"
1315
[attr.aria-labelledby]="ariaLabelledby"
1416
[attr.aria-describedby]="ariaDescribedby"
15-
(change)="_onInputChange($event)">
17+
(change)="_onInputInteraction($event)">
1618
<div class="mdc-radio__background">
1719
<div class="mdc-radio__outer-circle"></div>
1820
<div class="mdc-radio__inner-circle"></div>

src/material-experimental/mdc-radio/radio.scss

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
@use '@material/radio/radio' as mdc-radio;
22
@use '@material/radio/radio-theme' as mdc-radio-theme;
33
@use '@material/form-field' as mdc-form-field;
4+
@use '@material/touch-target' as mdc-touch-target;
45
@use '../mdc-helpers/mdc-helpers';
56
@use '../../cdk/a11y';
67
@use '../../material/core/style/layout-common';
@@ -25,6 +26,19 @@
2526
@include mdc-radio.without-ripple($query: animation);
2627
}
2728

29+
// Element used to provide a larger tap target for users on touch devices.
30+
.mat-mdc-radio-touch-target {
31+
@include mdc-touch-target.touch-target(
32+
$set-width: true,
33+
$query: mdc-helpers.$mat-base-styles-query);
34+
35+
[dir='rtl'] & {
36+
left: 0;
37+
right: 50%;
38+
transform: translate(50%, -50%);
39+
}
40+
}
41+
2842
// Note that this creates a square box around the circle, however it's consistent with
2943
// how IE/Edge treat native radio buttons in high contrast mode. We can't turn the border
3044
// into a dotted one, because it's too thick which causes the circles to look off.

src/material/radio/radio.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
[attr.aria-label]="ariaLabel"
1717
[attr.aria-labelledby]="ariaLabelledby"
1818
[attr.aria-describedby]="ariaDescribedby"
19-
(change)="_onInputChange($event)"
19+
(change)="_onInputInteraction($event)"
2020
(click)="_onInputClick($event)">
2121

2222
<!-- The ripple comes after the input so that we can target it with a CSS

src/material/radio/radio.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -588,24 +588,23 @@ export abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBase imple
588588
event.stopPropagation();
589589
}
590590

591-
/**
592-
* Triggered when the radio button received a click or the input recognized any change.
593-
* Clicking on a label element, will trigger a change event on the associated input.
594-
*/
595-
_onInputChange(event: Event) {
591+
/** Triggered when the radio button receives an interaction from the user. */
592+
_onInputInteraction(event: Event) {
596593
// We always have to stop propagation on the change event.
597594
// Otherwise the change event, from the input element, will bubble up and
598595
// emit its event object to the `change` output.
599596
event.stopPropagation();
600597

601-
const groupValueChanged = this.radioGroup && this.value !== this.radioGroup.value;
602-
this.checked = true;
603-
this._emitChangeEvent();
598+
if (!this.checked && !this.disabled) {
599+
const groupValueChanged = this.radioGroup && this.value !== this.radioGroup.value;
600+
this.checked = true;
601+
this._emitChangeEvent();
604602

605-
if (this.radioGroup) {
606-
this.radioGroup._controlValueAccessorChangeFn(this.value);
607-
if (groupValueChanged) {
608-
this.radioGroup._emitChangeEvent();
603+
if (this.radioGroup) {
604+
this.radioGroup._controlValueAccessorChangeFn(this.value);
605+
if (groupValueChanged) {
606+
this.radioGroup._emitChangeEvent();
607+
}
609608
}
610609
}
611610
}

tools/public_api_guard/material/radio.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export declare abstract class _MatRadioButtonBase extends _MatRadioButtonMixinBa
2525
constructor(radioGroup: _MatRadioGroupBase<_MatRadioButtonBase>, elementRef: ElementRef, _changeDetector: ChangeDetectorRef, _focusMonitor: FocusMonitor, _radioDispatcher: UniqueSelectionDispatcher, animationMode?: string, _providerOverride?: MatRadioDefaultOptions | undefined, tabIndex?: string);
2626
_isRippleDisabled(): boolean;
2727
_markForCheck(): void;
28-
_onInputChange(event: Event): void;
2928
_onInputClick(event: Event): void;
29+
_onInputInteraction(event: Event): void;
3030
protected _setDisabled(value: boolean): void;
3131
focus(options?: FocusOptions, origin?: FocusOrigin): void;
3232
ngAfterViewInit(): void;

0 commit comments

Comments
 (0)