Skip to content

Commit b06e7b6

Browse files
authored
Merge pull request #108 from UiPath/fix/a11y
a11y fixes
2 parents ca03324 + 370c263 commit b06e7b6

18 files changed

+283
-70
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
# v10.0.0-rc.2 (2020-10-28)
2+
* **grid** differentiate between user sort and programmatic sort events
3+
* **grid** a11y: announce only user `sort` events
4+
* **grid** a11y: expose translateable aria-label for checkboxes
5+
* **grid** added `matTooltip` for checkboxes
6+
* **suggest** a11y: fixes to title, specify `role` attributes for list
7+
* **suggest** a11y: announce current `option` on open
8+
* **suggest** announce "no results" msg if empty
9+
110
# v10.0.0-rc.1 (2020-10-15)
211
* **grid** fix multiple row selection with shift
312

package-lock.json

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular-components",
3-
"version": "10.0.0-rc.1",
3+
"version": "10.0.0-rc.2",
44
"author": {
55
"name": "UiPath Inc",
66
"url": "https://uipath.com"

projects/angular/components/ui-grid/src/components/ui-grid-search/ui-grid-search.component.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
<mat-icon *ngIf="!search.value"
3232
[matTooltip]="searchTooltip"
3333
[matTooltipDisabled]="tooltipDisabled"
34-
svgIcon="uipath:search"
3534
matSuffix
3635
class="svg-icon">
3736
<svg width="100%"

projects/angular/components/ui-grid/src/managers/sort-manager.spec.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,19 @@ describe('Component: UiGrid', () => {
5252
expect(manager.columns).toBe(columns);
5353
});
5454

55-
describe('Event: sort change', () => {
55+
it('should update sort event if columns change', () => {
56+
const cols = generateColumnList('random');
57+
cols.forEach(column => {
58+
column.sortable = true;
59+
column.sort = 'asc';
60+
});
61+
62+
manager.columns = cols;
63+
expect(Object.keys(manager.sort$.getValue()).length).toBe(4);
64+
expect(manager.sort$.getValue().userEvent).toBeFalse();
65+
});
66+
67+
describe('Event: user sort change', () => {
5668
it(`should cycle column sort from '' to 'asc'`, () => {
5769
const column = faker.helpers.randomize(columns);
5870
column.sort = '';
@@ -110,6 +122,7 @@ describe('Component: UiGrid', () => {
110122
).subscribe(sort => {
111123
expect(sort.field).toEqual(column.property!);
112124
expect(sort.direction).toEqual(column.sort);
125+
expect(sort.userEvent).toBeTrue();
113126
});
114127

115128
manager.changeSort(column);
@@ -129,6 +142,7 @@ describe('Component: UiGrid', () => {
129142
).subscribe(sort => {
130143
expect(sort.field).toEqual(first.property!);
131144
expect(sort.direction).toEqual(first.sort);
145+
expect(sort.userEvent).toBeTrue();
132146
});
133147

134148
manager.sort$
@@ -139,6 +153,7 @@ describe('Component: UiGrid', () => {
139153
).subscribe(sort => {
140154
expect(sort.field).toEqual(second.property!);
141155
expect(sort.direction).toEqual(second.sort);
156+
expect(sort.userEvent).toBeTrue();
142157
});
143158

144159
manager.changeSort(first);

projects/angular/components/ui-grid/src/managers/sort-manager.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@ export class SortManager<T> {
4848

4949
this._emitSort(sortedColumn);
5050
}
51-
51+
/**
52+
* Sort based on user action on column header
53+
*/
5254
public changeSort(column: UiGridColumnDirective<T>) {
5355
if (!column.sortable) { return; }
5456

@@ -58,18 +60,19 @@ export class SortManager<T> {
5860

5961
column.sort = SORT_CYCLE_MAP[column.sort];
6062

61-
this._emitSort(column);
63+
this._emitSort(column, true);
6264
}
6365

6466
public destroy() {
6567
this.sort$.complete();
6668
}
6769

68-
private _emitSort(column: UiGridColumnDirective<T>) {
70+
private _emitSort(column: UiGridColumnDirective<T>, userEvent = false) {
6971
const updatedSort = {
7072
direction: column.sort,
7173
field: column.property,
7274
title: column.title,
75+
userEvent,
7376
} as ISortModel<T>;
7477

7578
if (isEqual(this.sort$.getValue(), updatedSort)) { return; }

projects/angular/components/ui-grid/src/models/sortModel.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,9 @@ export interface ISortModel<T> {
2121
*
2222
*/
2323
title: string;
24+
/**
25+
* Sort event as a result of direct user intent to sort by a column.
26+
*
27+
*/
28+
userEvent?: boolean;
2429
}

projects/angular/components/ui-grid/src/ui-grid.component.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@
126126
[disabled]="!dataManager.length"
127127
[checked]="isEveryVisibleRowChecked"
128128
[indeterminate]="hasValueOnVisiblePage && !isEveryVisibleRowChecked"
129-
[aria-label]="checkboxLabel()"
129+
[matTooltip]="checkboxTooltip()"
130+
[aria-label]="checkboxTooltip()"
130131
tabindex="0">
131132
</mat-checkbox>
132133
</div>
@@ -172,7 +173,6 @@
172173
</div>
173174

174175
<div *ngIf="column.resizeable && !last"
175-
[class.is-resizing]="column.isResizing"
176176
(mousedown)="resizeManager.startResize($event, column)"
177177
class="ui-grid-resize-anchor">
178178
<mat-icon>
@@ -291,7 +291,8 @@
291291
(keyup.space)="checkShift($event)"
292292
(change)="handleSelection(index, row)"
293293
[checked]="selectionManager.isSelected(row)"
294-
[aria-label]="checkboxLabel(row)"
294+
[matTooltip]="checkboxTooltip(row)"
295+
[aria-label]="checkboxTooltip(row)"
295296
tabindex="0">
296297
</mat-checkbox>
297298
</div>
@@ -314,7 +315,8 @@
314315
(keyup.space)="checkShift($event)"
315316
(change)="handleSelection(index, row)"
316317
[checked]="selectionManager.isSelected(row)"
317-
[aria-label]="checkboxLabel(row)"
318+
[matTooltip]="checkboxTooltip(row)"
319+
[aria-label]="checkboxTooltip(row)"
318320
tabindex="0">
319321
</mat-checkbox>
320322
</div>

projects/angular/components/ui-grid/src/ui-grid.component.spec.ts

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -345,16 +345,34 @@ describe('Component: UiGrid', () => {
345345
});
346346

347347
describe('Feature: checkbox', () => {
348-
it('should check all rows if the header checkbox is clicked', () => {
348+
it('should have ariaLabel set correctly for toggle selection', () => {
349349
const checkboxHeader = fixture.debugElement.query(By.css('.ui-grid-header-cell.ui-grid-checkbox-cell'));
350+
const matCheckbox = checkboxHeader.query(By.css('mat-checkbox')).componentInstance as MatCheckbox;
351+
352+
expect(matCheckbox.checked).toEqual(false);
353+
expect(matCheckbox.ariaLabel).toEqual('Select all');
350354

351355
const checkboxInput = checkboxHeader.query(By.css('input'));
352356
checkboxInput.nativeElement.dispatchEvent(EventGenerator.click);
353357

354358
fixture.detectChanges();
355359

360+
361+
expect(matCheckbox.checked).toEqual(true);
362+
expect(matCheckbox.ariaLabel).toEqual('Deselect all');
363+
});
364+
365+
it('should check all rows if the header checkbox is clicked', () => {
366+
const checkboxHeader = fixture.debugElement.query(By.css('.ui-grid-header-cell.ui-grid-checkbox-cell'));
356367
const matCheckbox = checkboxHeader.query(By.css('mat-checkbox')).componentInstance as MatCheckbox;
357368

369+
expect(matCheckbox.checked).toEqual(false);
370+
371+
const checkboxInput = checkboxHeader.query(By.css('input'));
372+
checkboxInput.nativeElement.dispatchEvent(EventGenerator.click);
373+
374+
fixture.detectChanges();
375+
358376
expect(matCheckbox.checked).toEqual(true);
359377

360378
const rowCheckboxList = fixture.debugElement
@@ -388,7 +406,10 @@ describe('Component: UiGrid', () => {
388406

389407
expect(rowCheckboxList.length).toEqual(data.length);
390408

391-
rowCheckboxList.forEach(checkbox => expect(checkbox.checked).toEqual(true));
409+
rowCheckboxList.forEach((checkbox, i) => {
410+
expect(checkbox.checked).toEqual(true);
411+
expect(checkbox.ariaLabel).toEqual(`Deselect row ${i}`);
412+
});
392413

393414
expect(grid.selectionManager.selected.length).toEqual(data.length);
394415
expect(grid.selectionManager.selected).toEqual(data);
@@ -398,7 +419,10 @@ describe('Component: UiGrid', () => {
398419
fixture.detectChanges();
399420

400421
expect(matCheckbox.checked).toEqual(false);
401-
rowCheckboxList.forEach(checkbox => expect(checkbox.checked).toEqual(false));
422+
rowCheckboxList.forEach((checkbox, i) => {
423+
expect(checkbox.checked).toEqual(false);
424+
expect(checkbox.ariaLabel).toEqual(`Select row ${i}`);
425+
});
402426
expect(grid.hasValueOnVisiblePage).toEqual(false);
403427
});
404428

@@ -478,7 +502,7 @@ describe('Component: UiGrid', () => {
478502

479503
rowCheckboxInputList[10].nativeElement.dispatchEvent(EventGenerator.click);
480504

481-
for (let i = 0; i <= 10; i ++) {
505+
for (let i = 0; i <= 10; i++) {
482506
expect(grid.selectionManager.isSelected(data[i])).toBeTrue();
483507
}
484508
});

projects/angular/components/ui-grid/src/ui-grid.component.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ import {
3232
import {
3333
debounceTime,
3434
distinctUntilChanged,
35+
filter,
3536
map,
3637
observeOn,
37-
skip,
3838
switchMap,
3939
take,
4040
takeUntil,
@@ -114,7 +114,7 @@ export class UiGridComponent<T extends IGridDataEntry> extends ResizableGrid<T>
114114
*
115115
*/
116116
public get isEveryVisibleRowChecked() {
117-
return this.dataManager.length &&
117+
return !!this.dataManager.length &&
118118
this.dataManager.every(row => this.selectionManager.isSelected(row!));
119119
}
120120

@@ -499,7 +499,9 @@ export class UiGridComponent<T extends IGridDataEntry> extends ResizableGrid<T>
499499
msg => this._queuedAnnouncer.enqueue(msg),
500500
this.intl,
501501
this.dataManager.data$,
502-
this.sortManager.sort$.pipe(skip(1)),
502+
this.sortManager.sort$.pipe(
503+
filter(({ userEvent }) => !!userEvent),
504+
),
503505
this.refresh,
504506
this.footer && this.footer.pageChange,
505507
);
@@ -638,10 +640,23 @@ export class UiGridComponent<T extends IGridDataEntry> extends ResizableGrid<T>
638640
}
639641

640642
/**
641-
* Determines the `checkbox` `aria-label`.
643+
* Determines the `checkbox` `matToolTip`.
642644
*
643645
* @param [row] The row for which the label is computed.
644646
*/
647+
public checkboxTooltip(row?: T): string {
648+
if (!row) {
649+
return this.intl.checkboxTooltip(this.isEveryVisibleRowChecked);
650+
}
651+
652+
return this.intl.checkboxTooltip(this.selectionManager.isSelected(row), this.dataManager.indexOf(row));
653+
}
654+
655+
/**
656+
* Determines the `checkbox` aria-label`.
657+
* **DEPRECATED**
658+
* @param [row] The row for which the label is computed.
659+
*/
645660
public checkboxLabel(row?: T): string {
646661
if (!row) {
647662
return `${this.isEveryVisibleRowChecked ? 'select' : 'deselect'} all`;

0 commit comments

Comments
 (0)