ACS-3550 Fixed accessibility issues related with move and copy dialogs (#7961)

* ACS-3550 Fixed accessibility issues related with move and copy dialogs

* ACS-3550 Revert changes for button role for cells

* ACS-3550 Shorter css rule

* ACS-3550 Fixed lint issues

* ACS-3550 Changed selector to fix e2e tests
This commit is contained in:
AleksanderSklorz 2022-11-11 21:20:05 +01:00 committed by GitHub
parent 1109a73a19
commit ba05d3a1df
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 55 additions and 18 deletions

View File

@ -3,6 +3,7 @@
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate">
<button
id="dropdown-breadcrumb-button"
[tabindex]="hasPreviousNodes() ? 0 : -1"
class="adf-dropdown-breadcrumb-trigger"
(click)="open()"
@ -18,7 +19,8 @@
#dropdown
*ngIf="hasPreviousNodes()"
tabindex="-1"
data-automation-id="dropdown-breadcrumb-path">
data-automation-id="dropdown-breadcrumb-path"
aria-labelledby="dropdown-breadcrumb-button">
<mat-option
*ngFor="let node of previousNodes;"

View File

@ -47,7 +47,7 @@
</div>
</ng-container>
<ng-template #loading>
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'CORE.METADATA.BASIC.DATA_LOADING' | translate">
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'DATA_LOADING' | translate">
</mat-progress-bar>
</ng-template>
</ng-container>

View File

@ -45,7 +45,7 @@
<adf-toolbar>
<adf-toolbar-title>
<ng-container *ngIf="!showBreadcrumbs()">
<span role="heading" aria-level="3" class="adf-search-results-label">{{ 'NODE_SELECTOR.SEARCH_RESULTS' | translate }}</span>
<h2 class="adf-search-results-label">{{ 'NODE_SELECTOR.SEARCH_RESULTS' | translate }}</h2>
</ng-container>
<adf-dropdown-breadcrumb *ngIf="showBreadcrumbs()"
class="adf-content-node-selector-content-breadcrumb"
@ -86,10 +86,11 @@
(folderChange)="onFolderChange($event)"
(ready)="onFolderLoaded($event)"
(nodeSelected)="onCurrentSelection($event)"
[class.adf-content-node-selector-content-list-empty]="emptyList"
data-automation-id="content-node-selector-document-list">
<adf-custom-empty-content-template>
<div>{{ 'NODE_SELECTOR.NO_RESULTS' | translate }}</div>
<div aria-live="polite">{{ 'NODE_SELECTOR.NO_RESULTS' | translate }}</div>
</adf-custom-empty-content-template>
<data-columns>

View File

@ -1,7 +1,7 @@
/* stylelint-disable no-descending-specificity */
$content-node-selector-thumbnail-width: 35px !default;
.adf-search-results-label {
h2.adf-search-results-label {
flex: 1;
font-weight: 600;
font-size: var(--theme-body-1-font-size);
@ -95,6 +95,13 @@ $content-node-selector-thumbnail-width: 35px !default;
overflow: auto;
border: 1px solid var(--theme-border-color);
border-top: 0;
position: relative;
&-empty + adf-infinite-pagination {
position: absolute;
bottom: 0;
width: 100%;
}
.adf-highlight {
color: var(--theme-primary-color);

View File

@ -80,6 +80,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
private showSiteList = true;
private showSearchField = true;
private showCounter = false;
private _emptyList = true;
/** If true will restrict the search and breadcrumbs to the currentFolderId */
@Input()
@ -295,6 +296,10 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
return this._chosenNode;
}
get emptyList(): boolean {
return this._emptyList;
}
getSelectedCount(): number {
return this.chosenNode?.length || 0;
}
@ -567,6 +572,9 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
* Attempts to set the currently loaded node
*/
onFolderLoaded(nodePaging: NodePaging): void {
setTimeout(() => {
this._emptyList = !this.documentList.data.getRows().length;
});
this.updatePaginationAfterRowFilter(nodePaging);
if (!this.showingSearchResults) {
this.attemptNodeSelection(this.documentList.folderNode);

View File

@ -1,9 +1,4 @@
<header
mat-dialog-title
data-automation-id="content-node-selector-title">
<h2>{{title}}</h2>
</header>
<h1 mat-dialog-title data-automation-id="content-node-selector-title">{{title}}</h1>
<mat-tab-group class="adf-content-node-selector-dialog-content"
mat-align-tabs="start"
(selectedIndexChange)="onTabSelectionChange($event)"

View File

@ -8,9 +8,11 @@
class="adf-site-dropdown-list-element"
id="site-dropdown"
placeholder="{{placeholder | translate}}"
[aria-label]="ariaLabel"
floatPlaceholder="never"
[(value)]="selected"
(selectionChange)="selectedSite($event)">
(selectionChange)="selectedSite($event)"
role="listbox">
<mat-option *ngFor="let site of siteList?.list.entries;" [value]="site">
{{ site.entry.title | translate}}
</mat-option>

View File

@ -19,6 +19,8 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } fro
import { SitesService, LogService, InfiniteSelectScrollDirective } from '@alfresco/adf-core';
import { SitePaging, SiteEntry } from '@alfresco/js-api';
import { MatSelectChange } from '@angular/material/select';
import {LiveAnnouncer} from '@angular/cdk/a11y';
import {TranslateService} from '@ngx-translate/core';
/* eslint-disable no-shadow */
/* eslint-disable @typescript-eslint/naming-convention */
@ -74,20 +76,28 @@ export class DropdownSitesComponent implements OnInit {
private loading = true;
private skipCount = 0;
private _ariaLabel = '';
selected: SiteEntry = null;
MY_FILES_VALUE = '-my-';
constructor(private sitesService: SitesService,
private logService: LogService) {
private logService: LogService,
private liveAnnouncer: LiveAnnouncer,
private translateService: TranslateService) {
}
ngOnInit() {
this.updateAriaLabel(this.selected);
if (!this.siteList) {
this.loadSiteList();
}
}
get ariaLabel(): string {
return this._ariaLabel;
}
loadAllOnScroll() {
if (this.isInfiniteScrollingEnabled()) {
this.loading = true;
@ -96,6 +106,11 @@ export class DropdownSitesComponent implements OnInit {
}
selectedSite(event: MatSelectChange) {
this.updateAriaLabel(event.value);
this.liveAnnouncer.announce(this.translateService.instant('ADF_DROPDOWN.SELECTION_ARIA_LABEL', {
placeholder: this.translateService.instant(this.placeholder),
selectedOption: this.translateService.instant(event.value.entry.title)
}));
this.change.emit(event.value);
}
@ -140,6 +155,7 @@ export class DropdownSitesComponent implements OnInit {
}
this.selected = this.siteList.list.entries.find((site: SiteEntry) => site.entry.id === this.value);
this.updateAriaLabel(this.selected);
if (this.value && !this.selected && this.siteListHasMoreItems()) {
this.loadSiteList();
@ -174,4 +190,8 @@ export class DropdownSitesComponent implements OnInit {
return site.entry.visibility === 'PUBLIC' ||
!!site.relations.members.list.entries.find((member) => member.entry.id.toLowerCase() === loggedUserName.toLowerCase());
}
private updateAriaLabel(site: SiteEntry): void {
this._ariaLabel = `${this.translateService.instant(this.placeholder)} ${site ? this.translateService.instant(site.entry.title) : ''}`;
}
}

View File

@ -20,6 +20,7 @@
"CLAIM": "CLAIM",
"UNCLAIM": "RELEASE",
"START PROCESS": "START PROCESS",
"DATA_LOADING": "Data is loading",
"NOTIFICATIONS": {
"NO_MESSAGE": "You have no notifications at this time.",
"TITLE": "Notifications",
@ -219,8 +220,7 @@
"CREATED_DATE": "Created Date",
"MODIFIER": "Modifier",
"MODIFIED_DATE": "Modified Date",
"CONTENT_TYPE": "Content Type",
"DATA_LOADING": "Data is loading"
"CONTENT_TYPE": "Content Type"
},
"CONTENT_TYPE": {
"DIALOG": {
@ -581,6 +581,7 @@
}
},
"ADF_DROPDOWN": {
"LOADING": "Loading..."
"LOADING": "Loading...",
"SELECTION_ARIA_LABEL": "{{placeholder}} listbox {{selectedOption}}"
}
}

View File

@ -11,5 +11,6 @@
<mat-progress-bar *ngIf="isLoading"
mode="indeterminate"
class="adf-infinite-pagination-spinner"
data-automation-id="adf-infinite-pagination-spinner"></mat-progress-bar>
data-automation-id="adf-infinite-pagination-spinner"
[attr.aria-label]="'DATA_LOADING' | translate"></mat-progress-bar>
</div>

View File

@ -29,7 +29,7 @@ import { TestElement } from '../../core/public-api';
export class ContentNodeSelectorDialogPage {
dialog = $(`adf-content-node-selector`);
header = this.dialog.$(`header[data-automation-id='content-node-selector-title']`);
header = this.dialog.$(`h1[data-automation-id='content-node-selector-title']`);
searchInputElement = this.dialog.$(`input[data-automation-id='content-node-selector-search-input']`);
searchLabel = this.dialog.$('.adf-content-node-selector-content-input .mat-form-field-label');
selectedRow = this.dialog.$(`adf-datatable-row[class*="adf-is-selected"]`);