Skip to content

Commit b582aea

Browse files
committed
fix(dialog): dialog content not being read out by screen readers
Currently we focus the first focusable element inside a dialog as per the accessibility recommendations, however moving focus to the first item causes some screen readers not to read out the rest of the dialog content. These changes switch to focusing the dialog container by default which allows screen readers to read out everything. If users press tab, they'll land on the first tabbable element anyways. The old behavior can still be opted into via the `autoFocus` option. Fixes #10591.
1 parent 61b29bf commit b582aea

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

e2e/components/dialog-e2e.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('dialog', () => {
5959
await element(by.id('default')).click();
6060

6161
await waitForDialog();
62-
await expectFocusOn('mat-dialog-container input');
62+
await expectFocusOn('mat-dialog-container');
6363
});
6464

6565
it('should restore focus to the element that opened the dialog', async () => {
@@ -76,7 +76,7 @@ describe('dialog', () => {
7676
await element(by.id('default')).click();
7777

7878
await waitForDialog();
79-
await pressKeys(Key.TAB, Key.TAB, Key.TAB);
79+
await pressKeys(Key.TAB, Key.TAB, Key.TAB, Key.TAB);
8080
await expectFocusOn('#close');
8181
});
8282

src/lib/dialog/dialog-config.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,11 @@ export class MatDialogConfig<D = any> {
9595
/** Aria label to assign to the dialog element */
9696
ariaLabel?: string | null = null;
9797

98+
// Note that this is disabled by default, because while the a11y recommendations are to focus
99+
// the first focusable element, doing so prevents screen readers from reading out the
100+
// rest of the dialog's content.
98101
/** Whether the dialog should focus the first focusable element on open. */
99-
autoFocus?: boolean = true;
102+
autoFocus?: boolean = false;
100103

101104
/**
102105
* Whether the dialog should restore focus to the

src/lib/dialog/dialog.spec.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -966,18 +966,32 @@ describe('MatDialog', () => {
966966
beforeEach(() => document.body.appendChild(overlayContainerElement));
967967
afterEach(() => document.body.removeChild(overlayContainerElement));
968968

969-
it('should focus the first tabbable element of the dialog on open', fakeAsync(() => {
969+
it('should focus the dialog container by default', fakeAsync(() => {
970970
dialog.open(PizzaMsg, {
971-
viewContainerRef: testViewContainerRef
971+
viewContainerRef: testViewContainerRef,
972972
});
973973

974974
viewContainerFixture.detectChanges();
975975
flushMicrotasks();
976976

977977
expect(document.activeElement!.tagName)
978-
.toBe('INPUT', 'Expected first tabbable element (input) in the dialog to be focused.');
978+
.toBe('MAT-DIALOG-CONTAINER', 'Expected dialog container to be focused.');
979979
}));
980980

981+
it('should focus the first tabbable element of the dialog on open when autoFocus is enabled',
982+
fakeAsync(() => {
983+
dialog.open(PizzaMsg, {
984+
viewContainerRef: testViewContainerRef,
985+
autoFocus: true
986+
});
987+
988+
viewContainerFixture.detectChanges();
989+
flushMicrotasks();
990+
991+
expect(document.activeElement!.tagName)
992+
.toBe('INPUT', 'Expected first tabbable element (input) in the dialog to be focused.');
993+
}));
994+
981995
it('should allow disabling focus of the first tabbable element', fakeAsync(() => {
982996
dialog.open(PizzaMsg, {
983997
viewContainerRef: testViewContainerRef,

0 commit comments

Comments
 (0)