diff --git a/src/app/annuaire/result-list/result-list.component.html b/src/app/annuaire/result-list/result-list.component.html index 984e8962a08b049191fca2ce7fbde11842925b17..698532a6662266dea585e5e6e9fd91220e787099 100644 --- a/src/app/annuaire/result-list/result-list.component.html +++ b/src/app/annuaire/result-list/result-list.component.html @@ -1,7 +1,7 @@ <div class="results" id="resultList"> <div *ngIf="!isLogged && !isLoading" class="notConnected"> - <img src="../../assets/ico/annuaire-unlogged.svg" alt="Illustration annuaire" /> - <div class="count" [ngPlural]="totalUserResult"> + <img src="../../assets/ico/annuaire-unlogged.svg" alt="" /> + <div class="count" aria-live="polite" [ngPlural]="totalUserResult"> <ng-template ngPluralCase="0">Aucun membre n'est présent dans l'annuaire Rés'in</ng-template> <ng-template ngPluralCase="1">1 membre est présent dans l'annuaire Rés'in</ng-template> <ng-template ngPluralCase="other"> @@ -46,10 +46,12 @@ [showAppointment]="true" [showContactInfo]="false" [showEmployer]="true" + (keydown)="onMemberCardKeydown($event)" /> <div *ngIf="showPagination && !isLoading" class="pagination"> <p>{{ userList.length }} membres affichés sur {{ totalUserResult }}</p> <app-button + aria-live="polite" [label]="'Voir plus'" [variant]="'primaryBlack'" [size]="'medium'" @@ -61,6 +63,6 @@ </div> </ng-container> <div *ngIf="isLoading" class="loader" aria-busy="true"> - <img class="loader-gif" src="/assets/gif/loader_circle.gif" alt /> + <img class="loader-gif" src="/assets/gif/loader_circle.gif" alt="Chargement en cours" /> </div> </div> diff --git a/src/app/annuaire/result-list/result-list.component.ts b/src/app/annuaire/result-list/result-list.component.ts index 032a7672dd146bec945c5a7c96d162ee186ea249..5a112acbb32f0ed00e61c7c64f2cef20d1e07d22 100644 --- a/src/app/annuaire/result-list/result-list.component.ts +++ b/src/app/annuaire/result-list/result-list.component.ts @@ -1,4 +1,13 @@ -import { AfterViewInit, Component, EventEmitter, Input, OnChanges, Output, SimpleChanges } from '@angular/core'; +import { + AfterViewInit, + Component, + ElementRef, + EventEmitter, + Input, + OnChanges, + Output, + SimpleChanges, +} from '@angular/core'; import { Router } from '@angular/router'; import { UserAnnuary } from '../../models/user.model'; import { WindowScrollService } from '../../shared/service/windowScroll.service'; @@ -12,6 +21,7 @@ export class ResultListComponent implements OnChanges, AfterViewInit { constructor( private router: Router, private windowScrollService: WindowScrollService, + private elementRef: ElementRef, ) {} @Input() userList: UserAnnuary[]; @Input() totalUserResult: number; @@ -21,13 +31,13 @@ export class ResultListComponent implements OnChanges, AfterViewInit { @Output() showMoreEvent = new EventEmitter<void>(); public maxPerPage = 20; public showPagination = false; + public keyboardEvent = false; + public nextChildIndex: number; ngAfterViewInit(): void { - // Delay required before all member-card components are displayed on the page - setTimeout( - () => document.getElementById('app-body')?.scrollTo({ top: this.windowScrollService.scrollYToPreserve.value }), - 10, - ); + requestAnimationFrame(() => { + document.getElementById('app-body')?.scrollTo({ top: this.windowScrollService.scrollYToPreserve.value }); + }); } ngOnChanges(changes: SimpleChanges): void { @@ -35,6 +45,13 @@ export class ResultListComponent implements OnChanges, AfterViewInit { this.showPagination = true; } if (this.userList.length >= this.totalUserResult) this.showPagination = false; + + // Accessibility: after click on "view more" button, send focus to the first newly displayed member card + if (this.keyboardEvent && this.nextChildIndex) { + requestAnimationFrame(() => { + this.setFocusOnFirstNewMemberCard(); + }); + } } public goToUser(userId: string): void { this.router.navigateByUrl(`/profile/${userId}`); @@ -48,7 +65,29 @@ export class ResultListComponent implements OnChanges, AfterViewInit { public resetFilters(): void { this.resetEvent.emit(); } + + public onMemberCardKeydown(event: KeyboardEvent): void { + switch (event.key) { + case 'ArrowUp': + case 'ArrowDown': + case 'Tab': + this.keyboardEvent = true; + break; + } + } + + private setFocusOnFirstNewMemberCard(): void { + const lastFocusedMemberCard = this.elementRef.nativeElement.querySelector( + `.users app-member-card:nth-child(${this.nextChildIndex}) > div`, + ); + if (lastFocusedMemberCard) { + const focusedElement = lastFocusedMemberCard as HTMLElement; + focusedElement.focus(); + } + } + public showMore(): void { + this.nextChildIndex = this.userList.length + 1; this.showMoreEvent.emit(); } } diff --git a/src/app/profile/profile-structure/profile-structure.component.html b/src/app/profile/profile-structure/profile-structure.component.html index 99411c79a4c04a508669d5e660b2ff906e258c7f..6ed99f9c6914a03aad9aa6c9f7f084faf2aafbc2 100644 --- a/src/app/profile/profile-structure/profile-structure.component.html +++ b/src/app/profile/profile-structure/profile-structure.component.html @@ -80,15 +80,30 @@ </div> <div class="sectionContent infoSection"> <div class="row"> - <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'address'" /> + <app-svg-icon + [attr.aria-label]="'Adresse postale'" + [iconClass]="'icon-20'" + [folder]="'tags'" + [icon]="'address'" + /> {{ getAddress() }} </div> <div *ngIf="structure.contactPhone" class="row"> - <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'phone'" /> + <app-svg-icon + [attr.aria-label]="'Numéro de téléphone'" + [iconClass]="'icon-20'" + [folder]="'tags'" + [icon]="'phone'" + /> {{ structure.contactPhone | phone }} </div> <div *ngIf="structure.contactMail" class="row"> - <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'mail'" /> + <app-svg-icon + [attr.aria-label]="'Adresse e-mail'" + [iconClass]="'icon-20'" + [folder]="'tags'" + [icon]="'mail'" + /> <a href="mailto:{{ structure.contactMail }}">{{ structure.contactMail }}</a> </div> </div> diff --git a/src/app/profile/profile.component.html b/src/app/profile/profile.component.html index 60b1b15c177a84a0aae23e812b9adbec9a28dfd8..324cf9783c356a3d949113e1373950fa99e249b9 100644 --- a/src/app/profile/profile.component.html +++ b/src/app/profile/profile.component.html @@ -44,11 +44,21 @@ </div> <div class="block contact"> <div class="row"> - <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'phone'" /> + <app-svg-icon + [attr.aria-label]="'Numéro de téléphone'" + [iconClass]="'icon-20'" + [folder]="'tags'" + [icon]="'phone'" + /> <div>{{ userProfile.phone | phone }}</div> </div> <div class="row"> - <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'mail'" /> + <app-svg-icon + [attr.aria-label]="'Adresse e-mail'" + [iconClass]="'icon-20'" + [folder]="'tags'" + [icon]="'mail'" + /> <a href="mailto:{{ userProfile.email }}">{{ userProfile.email }}</a> </div> <div *ngIf="isPublic && userProfile.withAppointment" class="row"> diff --git a/src/app/shared/components/collapsable-filter/collapsable-filter.component.html b/src/app/shared/components/collapsable-filter/collapsable-filter.component.html index 0c75310f9703c5aadbedc30e0976f07336188550..75c95e42854a66c8b70efa9bcb887a24771db14d 100644 --- a/src/app/shared/components/collapsable-filter/collapsable-filter.component.html +++ b/src/app/shared/components/collapsable-filter/collapsable-filter.component.html @@ -1,5 +1,6 @@ <button type="button" + [attr.aria-label]="'Déplier les filtres : ' + label" [ngClass]="{ expanded: expanded, active: active diff --git a/src/app/shared/components/member-card/member-card.component.html b/src/app/shared/components/member-card/member-card.component.html index fe07eb491cc33da9cdc508eb7d0e19c647b72152..720190e177624c4c2d3d6e28ec82bb4e0cab43ce 100644 --- a/src/app/shared/components/member-card/member-card.component.html +++ b/src/app/shared/components/member-card/member-card.component.html @@ -13,7 +13,7 @@ <p>{{ getJob() }}</p> <div *ngIf="showAppointment && member.withAppointment" class="appointment"> <app-svg-icon [iconClass]="'icon-20'" [folder]="'tags'" [icon]="'rdv'" /> - <span>Rendez-vous</span> + <span aria-label="Prise de rendez-vous possible">Rendez-vous</span> </div> </div> <div *ngIf="showContactInfo" class="infoDetails">