Skip to content

Commit

Permalink
fix(material/datepicker): correct structure for grid role (#23022)
Browse files Browse the repository at this point in the history
Previously, the grid in mat-datepicker was not strictly following the structure expected for the grid role. Additionally, this change adds an `<abbr>` element to the column headers such that VoiceOver can correctly read column headers.

Fixes #21357

(cherry picked from commit f0ddd54)
  • Loading branch information
jelbourn authored and mmalerba committed Jun 22, 2021
1 parent 5d17311 commit 539e4cd
Show file tree
Hide file tree
Showing 8 changed files with 19 additions and 12 deletions.
2 changes: 0 additions & 2 deletions src/material/datepicker/calendar-body.ts
Expand Up @@ -58,8 +58,6 @@ export interface MatCalendarUserEvent<D> {
styleUrls: ['calendar-body.css'],
host: {
'class': 'mat-calendar-body',
'role': 'grid',
'aria-readonly': 'true'
},
exportAs: 'matCalendarBody',
encapsulation: ViewEncapsulation.None,
Expand Down
4 changes: 4 additions & 0 deletions src/material/datepicker/calendar.scss
Expand Up @@ -122,3 +122,7 @@ $calendar-next-icon-transform: translateX(-2px) rotate(45deg);
height: $calendar-header-divider-width;
}
}

.mat-calendar-abbr {
text-decoration: none;
}
11 changes: 8 additions & 3 deletions src/material/datepicker/month-view.html
@@ -1,9 +1,14 @@
<table class="mat-calendar-table" role="presentation">
<table class="mat-calendar-table" role="grid">
<thead class="mat-calendar-table-header">
<tr>
<th scope="col" *ngFor="let day of _weekdays" [attr.aria-label]="day.long">{{day.narrow}}</th>
<!-- For the day-of-the-week column header, we use an `<abbr>` element because VoiceOver
ignores the `aria-label`. ChromeVox, however, does not read the full name
for the `<abbr>`, so we still set `aria-label` on the header element. -->
<th scope="col" *ngFor="let day of _weekdays" [attr.aria-label]="day.long">
<abbr class="mat-calendar-abbr" [attr.title]="day.long">{{day.narrow}}</abbr>
</th>
</tr>
<tr><th class="mat-calendar-table-header-divider" colspan="7" aria-hidden="true"></th></tr>
<tr><th aria-hidden="true" class="mat-calendar-table-header-divider" colspan="7"></th></tr>
</thead>
<tbody mat-calendar-body
[label]="_monthLabel"
Expand Down
2 changes: 1 addition & 1 deletion src/material/datepicker/month-view.spec.ts
Expand Up @@ -114,7 +114,7 @@ describe('MatMonthView', () => {
describe('a11y', () => {
it('should set the correct role on the internal table node', () => {
const table = monthViewNativeElement.querySelector('table')!;
expect(table.getAttribute('role')).toBe('presentation');
expect(table.getAttribute('role')).toBe('grid');
});

it('should set the correct scope on the table headers', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/material/datepicker/multi-year-view.html
@@ -1,5 +1,5 @@
<table class="mat-calendar-table" role="presentation">
<thead class="mat-calendar-table-header">
<table class="mat-calendar-table" role="grid">
<thead aria-hidden="true" class="mat-calendar-table-header">
<tr><th class="mat-calendar-table-header-divider" colspan="4"></th></tr>
</thead>
<tbody mat-calendar-body
Expand Down
2 changes: 1 addition & 1 deletion src/material/datepicker/multi-year-view.spec.ts
Expand Up @@ -104,7 +104,7 @@ describe('MatMultiYearView', () => {
describe('a11y', () => {
it('should set the correct role on the internal table node', () => {
const table = multiYearViewNativeElement.querySelector('table')!;
expect(table.getAttribute('role')).toBe('presentation');
expect(table.getAttribute('role')).toBe('grid');
});

describe('calendar body', () => {
Expand Down
4 changes: 2 additions & 2 deletions src/material/datepicker/year-view.html
@@ -1,5 +1,5 @@
<table class="mat-calendar-table" role="presentation">
<thead class="mat-calendar-table-header">
<table class="mat-calendar-table" role="grid">
<thead aria-hidden="true" class="mat-calendar-table-header">
<tr><th class="mat-calendar-table-header-divider" colspan="4"></th></tr>
</thead>
<tbody mat-calendar-body
Expand Down
2 changes: 1 addition & 1 deletion src/material/datepicker/year-view.spec.ts
Expand Up @@ -118,7 +118,7 @@ describe('MatYearView', () => {
describe('a11y', () => {
it('should set the correct role on the internal table node', () => {
const table = yearViewNativeElement.querySelector('table')!;
expect(table.getAttribute('role')).toBe('presentation');
expect(table.getAttribute('role')).toBe('grid');
});

describe('calendar body', () => {
Expand Down

0 comments on commit 539e4cd

Please sign in to comment.