Skip to content

Commit 24e163c

Browse files
committed
fix(checkbox): redirect focus to underlying input element
Currently the `mat-checkbox` host element isn't focusable, which means that if consumers decided to use something like `cdkFocusInitial` on it, nothing would happen. These changes tweak the `tabindex` so the element is focusable and add a `focus` listener that'll redirect focus to the `input`. Relates to #13953.
1 parent ba31c72 commit 24e163c

File tree

3 files changed

+13
-2
lines changed

3 files changed

+13
-2
lines changed

src/lib/checkbox/checkbox.scss

+1
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ $_mat-checkbox-mark-stroke-size: 2 / 15 * $mat-checkbox-size !default;
182182

183183
cursor: pointer;
184184
-webkit-tap-highlight-color: transparent;
185+
outline: 0;
185186

186187
.mat-ripple-element:not(.mat-checkbox-persistent-ripple) {
187188
opacity: 0.16;

src/lib/checkbox/checkbox.spec.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,15 @@ describe('MatCheckbox', () => {
370370
expect(document.activeElement).toBe(inputElement);
371371
});
372372

373+
it('should focus on underlying input element when the host is focused', () => {
374+
expect(document.activeElement).not.toBe(inputElement);
375+
376+
checkboxNativeElement.focus();
377+
fixture.detectChanges();
378+
379+
expect(document.activeElement).toBe(inputElement);
380+
});
381+
373382
it('should forward the value to input element', () => {
374383
testComponent.checkboxValue = 'basic_checkbox';
375384
fixture.detectChanges();
@@ -790,7 +799,7 @@ describe('MatCheckbox', () => {
790799
fixture.detectChanges();
791800

792801
const checkbox = fixture.debugElement.query(By.directive(MatCheckbox)).nativeElement;
793-
expect(checkbox.getAttribute('tabindex')).toBeFalsy();
802+
expect(checkbox.getAttribute('tabindex')).toBe('-1');
794803
});
795804
});
796805

src/lib/checkbox/checkbox.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -119,12 +119,13 @@ export const _MatCheckboxMixinBase:
119119
host: {
120120
'class': 'mat-checkbox',
121121
'[id]': 'id',
122-
'[attr.tabindex]': 'null',
122+
'[attr.tabindex]': '-1', // Reset back to -1 so that the `focus` event still works.
123123
'[class.mat-checkbox-indeterminate]': 'indeterminate',
124124
'[class.mat-checkbox-checked]': 'checked',
125125
'[class.mat-checkbox-disabled]': 'disabled',
126126
'[class.mat-checkbox-label-before]': 'labelPosition == "before"',
127127
'[class._mat-animation-noopable]': `_animationMode === 'NoopAnimations'`,
128+
'(focus)': '_inputElement.nativeElement.focus()',
128129
},
129130
providers: [MAT_CHECKBOX_CONTROL_VALUE_ACCESSOR],
130131
inputs: ['disableRipple', 'color', 'tabIndex'],

0 commit comments

Comments
 (0)