Skip to content

Commit

Permalink
fix(platform): list accessibility issues
Browse files Browse the repository at this point in the history
  • Loading branch information
N1XUS committed Nov 28, 2023
1 parent f420e48 commit ae7518f
Show file tree
Hide file tree
Showing 25 changed files with 399 additions and 198 deletions.
11 changes: 11 additions & 0 deletions libs/core/src/lib/list/list-item/list-item.component.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* eslint-disable @typescript-eslint/member-ordering */
import {
AfterContentInit,
Attribute,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
Expand Down Expand Up @@ -132,6 +133,10 @@ export class ListItemComponent<T = any>
@HostBinding('class.fd-list__item--link')
link = false;

/** Aria-role attribute. */
@Input()
ariaRole: Nullable<string>;

/** @hidden */
@ContentChild(FD_RADIO_BUTTON_COMPONENT)
set radio(value: RadioButtonComponent) {
Expand Down Expand Up @@ -187,6 +192,11 @@ export class ListItemComponent<T = any>

/** @hidden */
@HostBinding('attr.role')
private get roleAttr(): string {
return this.ariaRole || this._role;
}

/** @hidden */
private _role = 'listitem'; // default for li elements

/** @hidden */
Expand All @@ -201,6 +211,7 @@ export class ListItemComponent<T = any>
constructor(
public readonly elementRef: ElementRef,
private readonly _changeDetectorRef: ChangeDetectorRef,
@Attribute('role') private readonly _defaultRole: string | null,
@Optional() @Inject(FD_LIST_UNREAD_INDICATOR) private readonly _unreadIndicator?: ListUnreadIndicator
) {
super(elementRef);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<h5>Cozy</h5>
<fdp-list>
<fdp-list-group-header groupHeaderTitle="Group header 1"></fdp-list-group-header>
<fdp-list ariaLabel="Grouped list">
<fdp-list-group-header groupHeaderTitle="Group header 1" ariaLabel="Group header 1"></fdp-list-group-header>
<fdp-standard-list-item title="Title1"></fdp-standard-list-item>
<fdp-standard-list-item title="Title2"></fdp-standard-list-item>
<fdp-standard-list-item title="Title3"></fdp-standard-list-item>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs';

import { ListDataSource, DataProvider } from '@fundamental-ngx/platform/shared';
import { DataProvider, ListDataSource } from '@fundamental-ngx/platform/shared';

export interface User {
firstName: string;
Expand Down Expand Up @@ -114,9 +114,13 @@ const list_elements: User[] = [
];

export class ListDataProvider extends DataProvider<User> {
private readonly _totalItems = new BehaviorSubject(0);
constructor() {
super();
}
getTotalItems(): Observable<number> {
return this._totalItems.asObservable();
}
fetch(params: Map<string, string>): Observable<User[]> {
let data = list_elements;
const name = params.get('name');
Expand All @@ -125,6 +129,8 @@ export class ListDataProvider extends DataProvider<User> {
data = data.filter((user) => user.firstName.toLowerCase().indexOf(keyword) > -1);
}

this._totalItems.next(data.length);

return of(data);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';
import { Observable, of } from 'rxjs';
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { BehaviorSubject, Observable, of } from 'rxjs';

import { ListDataSource, DataProvider } from '@fundamental-ngx/platform/shared';
import { DataProvider, ListDataSource } from '@fundamental-ngx/platform/shared';

export interface User {
firstName: string;
Expand Down Expand Up @@ -114,9 +114,13 @@ const list_elements: User[] = [
];

export class ListDataProvider extends DataProvider<User> {
private readonly _totalItems = new BehaviorSubject(0);
constructor() {
super();
}
getTotalItems(): Observable<number> {
return this._totalItems.asObservable();
}
fetch(params: Map<string, string>): Observable<User[]> {
let data = list_elements;
const name = params.get('name');
Expand All @@ -125,6 +129,9 @@ export class ListDataProvider extends DataProvider<User> {
data = data.filter((user) => user.firstName.toLowerCase().indexOf(keyword) > -1);
}

// Update total items count when new request completed.
this._totalItems.next(data.length);

return of(data);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
(selectedItemChange)="_showItemInfo($event)"
[selection]="true"
[ariaMultiselectable]="true"
role="listbox"
>
<fdp-standard-list-item *fdpItemDef="let address" [title]="address.name"></fdp-standard-list-item>
</fdp-list>
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
(selectedItemChange)="_showItemInfo($event)"
[selection]="true"
[ariaMultiselectable]="false"
role="listbox"
>
<fdp-standard-list-item
*fdpItemDef="let address"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
(keyup)="_onKeyUp($event)"
[attr.aria-label]="ariaLabel"
[attr.aria-level]="ariaLevel"
[attr.aria-posinet]="ariaPosinet"
[attr.role]="role"
[attr.aria-posinset]="ariaPosinset"
[attr.aria-setsize]="ariaSetSize | async"
[ariaRole]="_listItemRole"
[attr.aria-selected]="_selectedAttr"
>
<button #action class="fd-list__title" [attr.aria-label]="title" [attr.title]="title" (click)="_onActionClick()">
{{ title }}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable @typescript-eslint/member-ordering */
import { Component, ElementRef, ViewChild } from '@angular/core';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
Expand All @@ -6,6 +7,9 @@ import { RouterTestingModule } from '@angular/router/testing';
import { ActionListItemComponent } from './action-list-item.component';

import { PlatformListModule } from '../list.module';
import { SelectionType } from '../models/list';
import { BaseListItem } from '../base-list-item';
import { ListComponent } from '../list.component';

export interface Action {
title: string;
Expand All @@ -14,7 +18,7 @@ export interface Action {
@Component({
selector: 'fdp-test-fdp-action-list-item',
template: `
<fdp-list>
<fdp-list [selectionMode]="selectionMode">
<fdp-action-list-item title="Action 1"> </fdp-action-list-item>
<fdp-action-list-item title="Action 2"> </fdp-action-list-item>
<fdp-action-list-item title="Action 3"> </fdp-action-list-item>
Expand All @@ -26,9 +30,14 @@ class ActionListItemComponentTestComponent {
@ViewChild(ActionListItemComponent, { read: ElementRef, static: true })
actionListElement: ElementRef;

@ViewChild(ListComponent)
list: ListComponent<any>;

itemclick: string;
enterPress: string;

selectionMode: SelectionType = 'none';

onItemClick(): void {
this.itemclick = 'mouse is clicked';
}
Expand Down Expand Up @@ -84,10 +93,35 @@ describe('ActionListItemComponent', () => {
expect(actionItems[0].nativeElement.classList).toContain('fd-list__item--action');
});

it('Should display action item with role as option', () => {
it('Should display list item with role as listitem', () => {
const listContainer = fixture.debugElement.query(By.css('fdp-action-list-item .fd-list__item--action'));
fixture.detectChanges();
expect(listContainer.nativeElement.getAttribute('role')).toEqual('listitem');
});

it('Should display action item with role as option', async () => {
component.selectionMode = 'multi';
fixture.detectChanges();
const listItem = fixture.debugElement.query(By.css('fdp-action-list-item')).componentInstance as BaseListItem;
listItem.ngAfterViewInit();
fixture.detectChanges();
await fixture.whenStable();
let listContainer = fixture.debugElement.query(By.css('fdp-action-list-item .fd-list__item--action'));
expect(listContainer.nativeElement.getAttribute('role')).toEqual('option');
component.selectionMode = 'single';
fixture.detectChanges();
listItem.ngAfterViewInit();
fixture.detectChanges();
await fixture.whenStable();
listContainer = fixture.debugElement.query(By.css('fdp-action-list-item .fd-list__item--action'));
expect(listContainer.nativeElement.getAttribute('role')).toEqual('option');
component.selectionMode = 'none';
fixture.detectChanges();
listItem.ngAfterViewInit();
fixture.detectChanges();
await fixture.whenStable();
listContainer = fixture.debugElement.query(By.css('fdp-action-list-item .fd-list__item--action'));
expect(listContainer.nativeElement.getAttribute('role')).toEqual('listitem');
});

it('Should Action 1 Action 2 Action 3 and as Action 4 as list item', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { ENTER, SPACE } from '@angular/cdk/keycodes';
import {
ChangeDetectionStrategy,
Component,
Expand All @@ -7,7 +8,6 @@ import {
Output,
ViewChild
} from '@angular/core';
import { ENTER, SPACE } from '@angular/cdk/keycodes';

import { KeyUtil } from '@fundamental-ngx/cdk/utils';

Expand All @@ -22,7 +22,10 @@ export class ActionChangeEvent {
selector: 'fdp-action-list-item',
templateUrl: './action-list-item.component.html',
providers: [{ provide: BaseListItem, useExisting: forwardRef(() => ActionListItemComponent) }],
changeDetection: ChangeDetectionStrategy.OnPush
changeDetection: ChangeDetectionStrategy.OnPush,
host: {
role: 'none'
}
})
export class ActionListItemComponent extends BaseListItem {
/** Access button element*/
Expand Down
Loading

0 comments on commit ae7518f

Please sign in to comment.