Skip to content

Commit b4ce5ec

Browse files
authored
demo(list): Add accessibility demo page for list (#7020)
* demo(list): Add accessibility demo page for list * fix test * set default role for md-list * fix test * Add template file for list
1 parent 8b7a3af commit b4ce5ec

File tree

12 files changed

+183
-34
lines changed

12 files changed

+183
-34
lines changed

src/demo-app/a11y/a11y-module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
} from './dialog/dialog-a11y';
3030
import {ExpansionPanelAccessibilityDemo} from './expansion/expansion-a11y';
3131
import {GridListAccessibilityDemo} from './grid-list/grid-list-a11y';
32+
import {ListAccessibilityDemo} from './list/list-a11y';
3233
import {RadioAccessibilityDemo} from './radio/radio-a11y';
3334
import {ToolbarAccessibilityDemo} from './toolbar/toolbar-a11y';
3435
import {DatepickerAccessibilityDemo} from './datepicker/datepicker-a11y';
@@ -93,6 +94,7 @@ export class AccessibilityRoutingModule {}
9394
GridListAccessibilityDemo,
9495
IconAccessibilityDemo,
9596
InputAccessibilityDemo,
97+
ListAccessibilityDemo,
9698
MenuAccessibilityDemo,
9799
ProgressBarAccessibilityDemo,
98100
ProgressSpinnerAccessibilityDemo,

src/demo-app/a11y/a11y.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export class AccessibilityDemo implements OnDestroy {
4949
{name: 'Grid list', route: 'grid-list'},
5050
{name: 'Icon', route: 'icon'},
5151
{name: 'Input', route: 'input'},
52+
{name: 'List', route: 'list'},
5253
{name: 'Menu', route: 'menu'},
5354
{name: 'Progress bar', route: 'progress-bar'},
5455
{name: 'Progress spinner', route: 'progress-spinner'},

src/demo-app/a11y/list/list-a11y.html

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
<div class="demo-list">
2+
<section>
3+
<h2> Seasoning </h2>
4+
<p>Showing a non-interactive list of seasonings.</p>
5+
<mat-list role="list">
6+
<mat-list-item *ngFor="let item of items"> {{item}} </mat-list-item>
7+
</mat-list>
8+
</section>
9+
10+
11+
<section>
12+
<h2>Mailbox navigation</h2>
13+
<p>Showing a navigation list with links to google search</p>
14+
<mat-nav-list>
15+
<a mat-list-item *ngFor="let link of links"
16+
href="https://www.google.com/search?q={{link.name}}">
17+
{{link.name}}
18+
</a>
19+
</mat-nav-list>
20+
</section>
21+
22+
<section>
23+
<h2>Messages</h2>
24+
<p>
25+
Showing a list of messages, where each message item has sender's name, sender's avatar,
26+
message subject, and content of the message.
27+
</p>
28+
<mat-list role="list">
29+
<mat-list-item *ngFor="let message of messages">
30+
<img mat-list-avatar [src]="message.image" [alt]="message.from">
31+
<h3 mat-line> {{message.from}} </h3>
32+
<p mat-line> {{message.subject}} </p>
33+
<p mat-line class="demo-secondary-text"> {{message.message}} </p>
34+
</mat-list-item>
35+
</mat-list>
36+
37+
</section>
38+
39+
<section>
40+
<h2>Seasoning</h2>
41+
<p>Showing a non-interactive list of seasonings with dense style.</p>
42+
<mat-list dense>
43+
<mat-list-item *ngFor="let item of items"> {{item}} </mat-list-item>
44+
</mat-list>
45+
</section>
46+
47+
<section>
48+
<h2>Folders and notes for mailbox </h2>
49+
<p>Showing a list with two sections, "folders" and "notes".</p>
50+
<mat-list role="list">
51+
<h3 mat-subheader>Folders</h3>
52+
<mat-list-item *ngFor="let folder of folders">
53+
<mat-icon mat-list-icon>folder</mat-icon>
54+
<h4 mat-line>{{folder.name}}</h4>
55+
<p mat-line class="demo-secondary-text"> {{folder.updated}} </p>
56+
</mat-list-item>
57+
<mat-divider></mat-divider>
58+
<h3 mat-subheader>Notes</h3>
59+
<mat-list-item *ngFor="let note of notes">
60+
<mat-icon mat-list-icgon>note</mat-icon>
61+
<h4 mat-line>{{note.name}}</h4>
62+
<p mat-line class="demo-secondary-text"> {{note.updated}} </p>
63+
</mat-list-item>
64+
</mat-list>
65+
</section>
66+
</div>

src/demo-app/a11y/list/list-a11y.scss

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.demo-list {
2+
.mat-list, .mat-nav-list {
3+
border: 1px solid rgba(0, 0, 0, 0.12);
4+
max-width: 350px;
5+
margin: 20px 20px 0 0;
6+
}
7+
8+
.demo-secondary-text {
9+
color: rgba(0, 0, 0, 0.54);
10+
}
11+
}

src/demo-app/a11y/list/list-a11y.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {Component} from '@angular/core';
10+
11+
@Component({
12+
moduleId: module.id,
13+
selector: 'list-a11y',
14+
templateUrl: 'list-a11y.html',
15+
styleUrls: ['list-a11y.css']
16+
})
17+
export class ListAccessibilityDemo {
18+
items: string[] = [
19+
'Pepper',
20+
'Salt',
21+
'Paprika'
22+
];
23+
24+
messages = [
25+
{
26+
from: 'Nancy',
27+
subject: 'Brunch?',
28+
message: 'Did you want to go on Sunday? I was thinking that might work.',
29+
image: 'https://angular.io/generated/images/bios/julie-ralph.jpg'
30+
},
31+
{
32+
from: 'Mary',
33+
subject: 'Summer BBQ',
34+
message: 'Wish I could come, but I have some prior obligations.',
35+
image: 'https://angular.io/generated/images/bios/juleskremer.jpg'
36+
},
37+
{
38+
from: 'Bobby',
39+
subject: 'Oui oui',
40+
message: 'Do you have Paris reservations for the 15th? I just booked!',
41+
image: 'https://angular.io/generated/images/bios/jelbourn.jpg'
42+
}
43+
];
44+
45+
links = [
46+
{name: 'Inbox'},
47+
{name: 'Outbox'},
48+
{name: 'Spam'},
49+
{name: 'Trash'}
50+
51+
];
52+
53+
folders = [
54+
{name: 'Imported', updated: 'Miles'},
55+
{name: 'Important', updated: 'Tina'},
56+
{name: 'Unread', updated: 'Jeremy'},
57+
];
58+
59+
notes = [
60+
{name: 'Update screenshots', updated: 'Kara'},
61+
{name: 'Install new application', updated: 'Andrew'},
62+
];
63+
}

src/demo-app/a11y/routes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {ToolbarAccessibilityDemo} from './toolbar/toolbar-a11y';
2222
import {DatepickerAccessibilityDemo} from './datepicker/datepicker-a11y';
2323
import {IconAccessibilityDemo} from './icon/icon-a11y';
2424
import {InputAccessibilityDemo} from './input/input-a11y';
25+
import {ListAccessibilityDemo} from './list/list-a11y';
2526
import {MenuAccessibilityDemo} from './menu/menu-a11y';
2627
import {ProgressBarAccessibilityDemo} from './progress-bar/progress-bar-a11y';
2728
import {ProgressSpinnerAccessibilityDemo} from './progress-spinner/progress-spinner-a11y';
@@ -52,6 +53,7 @@ export const ACCESSIBILITY_DEMO_ROUTES: Routes = [
5253
{path: 'grid-list', component: GridListAccessibilityDemo},
5354
{path: 'icon', component: IconAccessibilityDemo},
5455
{path: 'input', component: InputAccessibilityDemo},
56+
{path: 'list', component: ListAccessibilityDemo},
5557
{path: 'menu', component: MenuAccessibilityDemo},
5658
{path: 'progress-bar', component: ProgressBarAccessibilityDemo},
5759
{path: 'progress-spinner', component: ProgressSpinnerAccessibilityDemo},

src/lib/list/list-module.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,12 @@ import {
1717
import {
1818
MatDividerCssMatStyler,
1919
MatList,
20+
MatNavList,
2021
MatListAvatarCssMatStyler,
21-
MatListCssMatStyler,
2222
MatListDivider,
2323
MatListIconCssMatStyler,
2424
MatListItem,
2525
MatListSubheaderCssMatStyler,
26-
MatNavListCssMatStyler,
2726
} from './list';
2827
import {MatListOption, MatSelectionList} from './selection-list';
2928

@@ -32,14 +31,13 @@ import {MatListOption, MatSelectionList} from './selection-list';
3231
imports: [MatLineModule, MatRippleModule, MatCommonModule, MatPseudoCheckboxModule, CommonModule],
3332
exports: [
3433
MatList,
34+
MatNavList,
3535
MatListItem,
3636
MatListDivider,
3737
MatListAvatarCssMatStyler,
3838
MatLineModule,
3939
MatCommonModule,
4040
MatListIconCssMatStyler,
41-
MatListCssMatStyler,
42-
MatNavListCssMatStyler,
4341
MatDividerCssMatStyler,
4442
MatListSubheaderCssMatStyler,
4543
MatPseudoCheckboxModule,
@@ -48,12 +46,11 @@ import {MatListOption, MatSelectionList} from './selection-list';
4846
],
4947
declarations: [
5048
MatList,
49+
MatNavList,
5150
MatListItem,
5251
MatListDivider,
5352
MatListAvatarCssMatStyler,
5453
MatListIconCssMatStyler,
55-
MatListCssMatStyler,
56-
MatNavListCssMatStyler,
5754
MatDividerCssMatStyler,
5855
MatListSubheaderCssMatStyler,
5956
MatSelectionList,

src/lib/list/list.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<ng-content></ng-content>
2+

src/lib/list/list.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,3 +150,12 @@ To add a divider, use `<mat-divider>`.
150150
</mat-list-item>
151151
</mat-list>
152152
```
153+
154+
### Accessibility
155+
By default, the list assumes that it will be used in a purely decorative fashion and thus sets no
156+
roles, ARIA attributes, or keyboard shortcuts. This is equivalent to having a sequence of <div>
157+
elements on the page. Any interactive content within the list should be given an appropriate
158+
accessibility treatment based on the specific workflow of your application.
159+
160+
If the list is used to present a list of non-interactive content items, then the list element should
161+
be given `role="list"` and each list item should be given `role="listitem"`.

src/lib/list/list.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ describe('MatList', () => {
115115

116116
let list = fixture.debugElement.children[0];
117117
let listItem = fixture.debugElement.children[0].query(By.css('mat-list-item'));
118-
expect(list.nativeElement.getAttribute('role')).toBe('list');
118+
expect(list.nativeElement.getAttribute('role')).toBeNull();
119119
expect(listItem.nativeElement.getAttribute('role')).toBe('listitem');
120120
});
121121

src/lib/list/list.ts

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -44,37 +44,34 @@ export class MatListDivider {}
4444
/** A Material Design list component. */
4545
@Component({
4646
moduleId: module.id,
47-
selector: 'mat-list, mat-nav-list',
48-
exportAs: 'matList, matNavList',
49-
host: {'role': 'list'},
50-
template: '<ng-content></ng-content>',
47+
selector: 'mat-nav-list',
48+
exportAs: 'matNavList',
49+
host: {
50+
'role': 'navigation',
51+
'class': 'mat-nav-list'
52+
},
53+
templateUrl: 'list.html',
5154
styleUrls: ['list.css'],
5255
inputs: ['disableRipple'],
5356
encapsulation: ViewEncapsulation.None,
5457
preserveWhitespaces: false,
5558
changeDetection: ChangeDetectionStrategy.OnPush,
5659
})
57-
export class MatList extends _MatListMixinBase implements CanDisableRipple {}
60+
export class MatNavList extends _MatListMixinBase implements CanDisableRipple {}
5861

59-
/**
60-
* Directive whose purpose is to add the mat- CSS styling to this selector.
61-
* @docs-private
62-
*/
63-
@Directive({
62+
@Component({
63+
moduleId: module.id,
6464
selector: 'mat-list',
65-
host: {'class': 'mat-list'}
66-
})
67-
export class MatListCssMatStyler {}
68-
69-
/**
70-
* Directive whose purpose is to add the mat- CSS styling to this selector.
71-
* @docs-private
72-
*/
73-
@Directive({
74-
selector: 'mat-nav-list',
75-
host: {'class': 'mat-nav-list'}
65+
exportAs: 'matList',
66+
templateUrl: 'list.html',
67+
host: {'class': 'mat-list'},
68+
styleUrls: ['list.css'],
69+
inputs: ['disableRipple'],
70+
encapsulation: ViewEncapsulation.None,
71+
preserveWhitespaces: false,
72+
changeDetection: ChangeDetectionStrategy.OnPush,
7673
})
77-
export class MatNavListCssMatStyler {}
74+
export class MatList extends _MatListMixinBase implements CanDisableRipple {}
7875

7976
/**
8077
* Directive whose purpose is to add the mat- CSS styling to this selector.
@@ -150,10 +147,9 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
150147
}
151148

152149
constructor(private _element: ElementRef,
153-
@Optional() private _list: MatList,
154-
@Optional() navList: MatNavListCssMatStyler) {
150+
@Optional() private _navList: MatNavList) {
155151
super();
156-
this._isNavList = !!navList;
152+
this._isNavList = !!_navList;
157153
}
158154

159155
ngAfterContentInit() {
@@ -162,7 +158,7 @@ export class MatListItem extends _MatListItemMixinBase implements AfterContentIn
162158

163159
/** Whether this list item should show a ripple effect when clicked. */
164160
_isRippleDisabled() {
165-
return !this._isNavList || this.disableRipple || this._list.disableRipple;
161+
return !this._isNavList || this.disableRipple || this._navList.disableRipple;
166162
}
167163

168164
_handleFocus() {

src/material-examples/list-overview/list-overview-example.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<mat-list>
1+
<mat-list role="list">
22
<mat-list-item>Item 1</mat-list-item>
33
<mat-list-item>Item 2</mat-list-item>
44
<mat-list-item>Item 3</mat-list-item>

0 commit comments

Comments
 (0)