From f2a4ae963484334427494d00afac04e40c2e0b96 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 10:34:17 +0200
Subject: [PATCH 1/8] WIP

---
 .../result-list/result-list.component.ts      |  8 ++--
 .../structure-access-modality.component.html  |  1 +
 .../structure-consent.component.html          |  2 +
 .../structure-labels.component.html           |  1 +
 .../checkbox-form.component.html              |  4 +-
 .../checkbox-form/checkbox-form.component.ts  |  1 +
 .../checkbox/checkbox.component.html          |  2 +-
 .../components/checkbox/checkbox.component.ts |  2 +-
 .../collapsable-filter.component.html         |  3 +-
 .../collapse-header.component.ts              |  1 +
 .../training-type-picker.component.html       |  8 +++-
 .../more-filters/more-filters.component.html  |  3 +-
 .../structure-list-search.component.html      |  5 ++
 .../structure-list-search.component.ts        | 47 ++++++++++++++++++-
 14 files changed, 76 insertions(+), 12 deletions(-)

diff --git a/src/app/annuaire/result-list/result-list.component.ts b/src/app/annuaire/result-list/result-list.component.ts
index 5a112acbb..152027e06 100644
--- a/src/app/annuaire/result-list/result-list.component.ts
+++ b/src/app/annuaire/result-list/result-list.component.ts
@@ -35,9 +35,9 @@ export class ResultListComponent implements OnChanges, AfterViewInit {
   public nextChildIndex: number;
 
   ngAfterViewInit(): void {
-    requestAnimationFrame(() => {
+    setTimeout(() => {
       document.getElementById('app-body')?.scrollTo({ top: this.windowScrollService.scrollYToPreserve.value });
-    });
+    }, 10);
   }
 
   ngOnChanges(changes: SimpleChanges): void {
@@ -48,9 +48,9 @@ export class ResultListComponent implements OnChanges, AfterViewInit {
 
     // Accessibility: after click on "view more" button, send focus to the first newly displayed member card
     if (this.keyboardEvent && this.nextChildIndex) {
-      requestAnimationFrame(() => {
+      setTimeout(() => {
         this.setFocusOnFirstNewMemberCard();
-      });
+      }, 0);
     }
   }
   public goToUser(userId: string): void {
diff --git a/src/app/form/form-view/structure-form/structure-access-modality/structure-access-modality.component.html b/src/app/form/form-view/structure-form/structure-access-modality/structure-access-modality.component.html
index 1a94130e2..13dde9e44 100644
--- a/src/app/form/form-view/structure-form/structure-access-modality/structure-access-modality.component.html
+++ b/src/app/form/form-view/structure-form/structure-access-modality/structure-access-modality.component.html
@@ -13,6 +13,7 @@
       <app-checkbox-form
         *ngFor="let module of accessModality.modules"
         [isChecked]="isInArray('accessModality', module.id)"
+        [id]="module.id"
         [text]="module.name"
         [iconSvg]="module.id"
         (checkEvent)="onCheckChange($event, 'categories.accessModality', module.id)"
diff --git a/src/app/form/form-view/structure-form/structure-consent/structure-consent.component.html b/src/app/form/form-view/structure-form/structure-consent/structure-consent.component.html
index c79ef6670..681a013e9 100644
--- a/src/app/form/form-view/structure-form/structure-consent/structure-consent.component.html
+++ b/src/app/form/form-view/structure-form/structure-consent/structure-consent.component.html
@@ -8,6 +8,7 @@
     </div>
     <app-checkbox-form
       text="J’accepte que mes informations soient enregistrées"
+      id="acceptDataBeSaved"
       (checkEvent)="acceptDataBeSaved($event)"
     />
   </div>
@@ -24,6 +25,7 @@
     <app-checkbox-form
       *ngIf="!isEditMode"
       text="J’accepte de partager les données de ma structure"
+      [id]="'acceptOpenData'"
       [isChecked]="false"
       (checkEvent)="acceptOpenData($event)"
     />
diff --git a/src/app/form/form-view/structure-form/structure-labels/structure-labels.component.html b/src/app/form/form-view/structure-form/structure-labels/structure-labels.component.html
index d3a639bf2..1a4ac7f1c 100644
--- a/src/app/form/form-view/structure-form/structure-labels/structure-labels.component.html
+++ b/src/app/form/form-view/structure-form/structure-labels/structure-labels.component.html
@@ -8,6 +8,7 @@
     <app-checkbox-form
       *ngFor="let module of labelsQualifications.modules.sort()"
       [isChecked]="isInArray(module.id, 'labelsQualifications')"
+      [id]="module.id"
       [text]="module.name"
       [iconSvg]="module.id"
       [iconType]="'labels'"
diff --git a/src/app/shared/components/checkbox-form/checkbox-form.component.html b/src/app/shared/components/checkbox-form/checkbox-form.component.html
index 9a5c736eb..11e104196 100644
--- a/src/app/shared/components/checkbox-form/checkbox-form.component.html
+++ b/src/app/shared/components/checkbox-form/checkbox-form.component.html
@@ -1,9 +1,9 @@
 <div class="checkbox" tabindex="-1" [ngClass]="{ selected: isChecked }" (click)="clicked()" (keydown.enter)="clicked()">
-  <app-checkbox [checked]="isChecked" />
+  <app-checkbox [checked]="isChecked" [id]="id" />
 
   <svg *ngIf="iconSvg" aria-hidden="true" class="icon" [ngClass]="iconType">
     <use [attr.xlink:href]="'assets/form/sprite.svg#' + iconSvg" />
   </svg>
 
-  <p id="checkboxLabel">{{ text }}</p>
+  <p id="{{ id }}">{{ text }}</p>
 </div>
diff --git a/src/app/shared/components/checkbox-form/checkbox-form.component.ts b/src/app/shared/components/checkbox-form/checkbox-form.component.ts
index 81f6046b0..553dfefec 100644
--- a/src/app/shared/components/checkbox-form/checkbox-form.component.ts
+++ b/src/app/shared/components/checkbox-form/checkbox-form.component.ts
@@ -6,6 +6,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
   styleUrls: ['./checkbox-form.component.scss'],
 })
 export class CheckboxFormComponent {
+  @Input({ required: true }) public id: string;
   @Input() public isChecked = false;
   @Input() public text: string;
   @Input() public iconSvg: string;
diff --git a/src/app/shared/components/checkbox/checkbox.component.html b/src/app/shared/components/checkbox/checkbox.component.html
index c2185f1c7..f0a9237a8 100644
--- a/src/app/shared/components/checkbox/checkbox.component.html
+++ b/src/app/shared/components/checkbox/checkbox.component.html
@@ -5,6 +5,6 @@
   [checked]="checked"
   [indeterminate]="indeterminate"
   [disabled]="disabled"
-  [attr.aria-labelledby]="'checkboxLabel'"
+  [attr.aria-labelledby]="id"
   (click)="action.emit($event)"
 />
diff --git a/src/app/shared/components/checkbox/checkbox.component.ts b/src/app/shared/components/checkbox/checkbox.component.ts
index 04cc9244c..7e25394b7 100644
--- a/src/app/shared/components/checkbox/checkbox.component.ts
+++ b/src/app/shared/components/checkbox/checkbox.component.ts
@@ -7,7 +7,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
 })
 export class CheckboxComponent {
   /** HTML id associated with for */
-  @Input() id: string;
+  @Input({ required: true }) id: string;
 
   /** Checked ? */
   @Input({ required: true }) checked: boolean;
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 75c95e428..21e02b156 100644
--- a/src/app/shared/components/collapsable-filter/collapsable-filter.component.html
+++ b/src/app/shared/components/collapsable-filter/collapsable-filter.component.html
@@ -1,6 +1,7 @@
 <button
   type="button"
-  [attr.aria-label]="'Déplier les filtres : ' + label"
+  aria-haspopup="true"
+  [attr.aria-label]="label + 'Déplier les filtres : '"
   [ngClass]="{
     expanded: expanded,
     active: active
diff --git a/src/app/shared/components/collapse/collapse-header/collapse-header.component.ts b/src/app/shared/components/collapse/collapse-header/collapse-header.component.ts
index ec62e8b0e..9683c91c0 100644
--- a/src/app/shared/components/collapse/collapse-header/collapse-header.component.ts
+++ b/src/app/shared/components/collapse/collapse-header/collapse-header.component.ts
@@ -5,6 +5,7 @@ import { Component, EventEmitter, Output } from '@angular/core';
   template: `<div
     class="collapse-header"
     role="button"
+    aria-haspopup="true"
     tabindex="0"
     [ngClass]="size"
     (click)="toggle.emit()"
diff --git a/src/app/shared/components/training-type-picker/training-type-picker.component.html b/src/app/shared/components/training-type-picker/training-type-picker.component.html
index 03741b86b..840073000 100644
--- a/src/app/shared/components/training-type-picker/training-type-picker.component.html
+++ b/src/app/shared/components/training-type-picker/training-type-picker.component.html
@@ -4,10 +4,16 @@
       <div class="collapseHeader">
         <app-checkbox
           [checked]="getCategoryCheckboxStatus(category) === 'checked'"
+          [id]="category.id"
           [indeterminate]="getCategoryCheckboxStatus(category) === 'halfChecked'"
           (action)="pickAllCategory(category); $event.stopPropagation()"
         />
-        <span class="titleCollapse">{{ category.name }}</span>
+        <span
+          class="titleCollapse"
+          id="{{ category.id }}"
+          [attr.aria-label]="category.name + '. Cocher pour tout sélectionner'"
+          >{{ category.name }}</span
+        >
       </div>
     </app-collapse-header>
     <app-collapse-content>
diff --git a/src/app/structure-list/components/more-filters/more-filters.component.html b/src/app/structure-list/components/more-filters/more-filters.component.html
index 9edc35ba1..40035414c 100644
--- a/src/app/structure-list/components/more-filters/more-filters.component.html
+++ b/src/app/structure-list/components/more-filters/more-filters.component.html
@@ -33,11 +33,12 @@
           <div class="collapseHeader">
             <app-checkbox
               [size]="'medium'"
+              [id]="c.id"
               [checked]="getCategoryCheckboxStatus(c) === 'checked'"
               [indeterminate]="getCategoryCheckboxStatus(c) === 'halfChecked'"
               (action)="handleCategoryCheckBox($event, c); $event.stopPropagation()"
             />
-            <span>{{ c.name }}</span>
+            <span id="{{ c.id }}" [attr.aria-label]="c.name + '. Cocher pour tout sélectionner'">{{ c.name }}</span>
           </div>
         </app-collapse-header>
         <app-collapse-content>
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
index c8af2c9b6..ec9d1c49d 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
@@ -7,24 +7,28 @@
         [expanded]="modalTypeOpened === TypeModal.accompaniment"
         [active]="numberAccompanimentChecked > 0"
         (toggle)="openModal(TypeModal.accompaniment)"
+        (keyup)="onKeyboardNavigation($event)"
       />
       <app-collapsable-filter
         [label]="'Compétences numériques'"
         [expanded]="modalTypeOpened === TypeModal.training"
         [active]="numberTrainingChecked > 0"
         (toggle)="openModal(TypeModal.training)"
+        (keyup)="onKeyboardNavigation($event)"
       />
       <app-collapsable-filter
         [label]="'Public'"
         [expanded]="modalTypeOpened === TypeModal.public"
         [active]="numberPublicChecked > 0"
         (toggle)="openModal(TypeModal.public)"
+        (keyup)="onKeyboardNavigation($event)"
       />
       <app-collapsable-filter
         [label]="'Matériel & wifi'"
         [expanded]="modalTypeOpened === TypeModal.equipments"
         [active]="numberEquipmentChecked > 0"
         (toggle)="openModal(TypeModal.equipments)"
+        (keyup)="onKeyboardNavigation($event)"
       />
       <app-checkbox-filter
         [module]="{
@@ -51,6 +55,7 @@
           [modules]="checkedModulesFilter"
           (searchEvent)="fetchResults($event)"
           (closeEvent)="closeModal()"
+          (keyup)="onKeyboardNavigation($event)"
         />
       </div>
     </div>
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index 9c0aeeabd..a19588e8c 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -1,4 +1,4 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
+import { Component, ElementRef, EventEmitter, Input, OnInit, Output } from '@angular/core';
 import { ActivatedRoute, Router } from '@angular/router';
 import { Utils } from '../../../utils/utils';
 import { Theme } from '../../enum/themes.enum';
@@ -38,12 +38,14 @@ export class StructureListSearchComponent implements OnInit {
   public prmAdded = false;
 
   public hasUrlParams = false;
+  public keyboardEvent = false;
 
   constructor(
     public searchService: SearchService,
     private activatedRoute: ActivatedRoute,
     private route: ActivatedRoute,
     private router: Router,
+    private elementRef: ElementRef,
   ) {}
   ngOnInit(): void {
     this.searchInput = this.activatedRoute.snapshot.queryParamMap.get('query');
@@ -175,11 +177,54 @@ export class StructureListSearchComponent implements OnInit {
     // if modal already opened, reset type
     if (this.modalTypeOpened === modalType) {
       this.closeModal();
+      // Accessibility: when navigating with keyboard and closing a filter modal, send focus back to filters
+      if (this.keyboardEvent) {
+        this.setFocusOnFilters();
+      }
     } else if (this.modalTypeOpened !== modalType) {
       this.modalTypeOpened = modalType;
+
+      // Accessibility: when navigating with keyboard and opening a filter modal, send focus to the first focusable element of the opened modal
+      if (this.keyboardEvent) {
+        this.setFocusOnOpenedModal();
+      }
+    }
+  }
+
+  // When filters and their modal are in the same component, we can remove onKeyboardNavigation, setFocusOnOpenedModal, and setFocusOnFilters.
+  // because the focus will then flow normally between the filter and the modal
+  public onKeyboardNavigation(event: KeyboardEvent): void {
+    switch (event.key) {
+      case 'ArrowUp':
+      case 'ArrowDown':
+      case 'Tab':
+        this.keyboardEvent = true;
+        break;
     }
   }
 
+  private setFocusOnOpenedModal(): void {
+    setTimeout(() => {
+      const modalFirstFocusableElement = this.elementRef.nativeElement.querySelector(
+        `.modalContent input, .modalContent button`,
+      );
+      if (modalFirstFocusableElement) {
+        const focusedElement = modalFirstFocusableElement as HTMLElement;
+        focusedElement.focus();
+      }
+    }, 0);
+  }
+
+  private setFocusOnFilters(): void {
+    setTimeout(() => {
+      const firstfilter = this.elementRef.nativeElement.querySelector(`.filters button`);
+      if (firstfilter) {
+        const focusedElement = firstfilter as HTMLElement;
+        focusedElement.focus();
+      }
+    }, 0);
+  }
+
   public closeModal(): void {
     this.modalTypeOpened = undefined;
   }
-- 
GitLab


From 599a44b7a0324cf4f4644ee92686a03ff8477543 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 14:55:22 +0200
Subject: [PATCH 2/8] wip improve checkbox labels

---
 .../components/checkbox-form/checkbox-form.component.html     | 2 +-
 src/app/shared/components/checkbox/checkbox.component.html    | 2 +-
 .../training-type-picker/training-type-picker.component.html  | 2 +-
 .../components/more-filters/more-filters.component.html       | 4 +++-
 4 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/app/shared/components/checkbox-form/checkbox-form.component.html b/src/app/shared/components/checkbox-form/checkbox-form.component.html
index 11e104196..6b56b0e7f 100644
--- a/src/app/shared/components/checkbox-form/checkbox-form.component.html
+++ b/src/app/shared/components/checkbox-form/checkbox-form.component.html
@@ -5,5 +5,5 @@
     <use [attr.xlink:href]="'assets/form/sprite.svg#' + iconSvg" />
   </svg>
 
-  <p id="{{ id }}">{{ text }}</p>
+  <p id="label-{{ id }}">{{ text }}</p>
 </div>
diff --git a/src/app/shared/components/checkbox/checkbox.component.html b/src/app/shared/components/checkbox/checkbox.component.html
index f0a9237a8..5460622bc 100644
--- a/src/app/shared/components/checkbox/checkbox.component.html
+++ b/src/app/shared/components/checkbox/checkbox.component.html
@@ -5,6 +5,6 @@
   [checked]="checked"
   [indeterminate]="indeterminate"
   [disabled]="disabled"
-  [attr.aria-labelledby]="id"
+  [attr.aria-labelledby]="'label-' + id"
   (click)="action.emit($event)"
 />
diff --git a/src/app/shared/components/training-type-picker/training-type-picker.component.html b/src/app/shared/components/training-type-picker/training-type-picker.component.html
index 840073000..0f96db8bc 100644
--- a/src/app/shared/components/training-type-picker/training-type-picker.component.html
+++ b/src/app/shared/components/training-type-picker/training-type-picker.component.html
@@ -10,7 +10,7 @@
         />
         <span
           class="titleCollapse"
-          id="{{ category.id }}"
+          id="label-{{ category.id }}"
           [attr.aria-label]="category.name + '. Cocher pour tout sélectionner'"
           >{{ category.name }}</span
         >
diff --git a/src/app/structure-list/components/more-filters/more-filters.component.html b/src/app/structure-list/components/more-filters/more-filters.component.html
index 40035414c..2820d736f 100644
--- a/src/app/structure-list/components/more-filters/more-filters.component.html
+++ b/src/app/structure-list/components/more-filters/more-filters.component.html
@@ -38,7 +38,9 @@
               [indeterminate]="getCategoryCheckboxStatus(c) === 'halfChecked'"
               (action)="handleCategoryCheckBox($event, c); $event.stopPropagation()"
             />
-            <span id="{{ c.id }}" [attr.aria-label]="c.name + '. Cocher pour tout sélectionner'">{{ c.name }}</span>
+            <span id="label-{{ c.id }}" [attr.aria-label]="c.name + '. Cocher pour tout sélectionner'">{{
+              c.name
+            }}</span>
           </div>
         </app-collapse-header>
         <app-collapse-content>
-- 
GitLab


From 8e75ae85ae8a1c582896d4c4ac107bdb0d597e4f Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 15:03:34 +0200
Subject: [PATCH 3/8] wip improve checkbox labels

---
 .../components/checkbox-form/checkbox-form.component.html   | 2 +-
 .../components/checkbox-form/checkbox-form.component.scss   | 2 +-
 src/app/shared/components/checkbox/checkbox.component.html  | 1 -
 .../training-type-picker.component.html                     | 6 +++---
 .../components/more-filters/more-filters.component.html     | 4 +---
 5 files changed, 6 insertions(+), 9 deletions(-)

diff --git a/src/app/shared/components/checkbox-form/checkbox-form.component.html b/src/app/shared/components/checkbox-form/checkbox-form.component.html
index 6b56b0e7f..7ebc8d9dc 100644
--- a/src/app/shared/components/checkbox-form/checkbox-form.component.html
+++ b/src/app/shared/components/checkbox-form/checkbox-form.component.html
@@ -5,5 +5,5 @@
     <use [attr.xlink:href]="'assets/form/sprite.svg#' + iconSvg" />
   </svg>
 
-  <p id="label-{{ id }}">{{ text }}</p>
+  <label for="{{ id }}">{{ text }}</label>
 </div>
diff --git a/src/app/shared/components/checkbox-form/checkbox-form.component.scss b/src/app/shared/components/checkbox-form/checkbox-form.component.scss
index 0078cd152..eb1760740 100644
--- a/src/app/shared/components/checkbox-form/checkbox-form.component.scss
+++ b/src/app/shared/components/checkbox-form/checkbox-form.component.scss
@@ -22,7 +22,7 @@ div.checkbox {
     min-width: 44px;
   }
 
-  p {
+  label {
     @include font-bold-16;
     color: $grey-1;
     text-align: left;
diff --git a/src/app/shared/components/checkbox/checkbox.component.html b/src/app/shared/components/checkbox/checkbox.component.html
index 5460622bc..17d7e6d70 100644
--- a/src/app/shared/components/checkbox/checkbox.component.html
+++ b/src/app/shared/components/checkbox/checkbox.component.html
@@ -5,6 +5,5 @@
   [checked]="checked"
   [indeterminate]="indeterminate"
   [disabled]="disabled"
-  [attr.aria-labelledby]="'label-' + id"
   (click)="action.emit($event)"
 />
diff --git a/src/app/shared/components/training-type-picker/training-type-picker.component.html b/src/app/shared/components/training-type-picker/training-type-picker.component.html
index 0f96db8bc..a62a4c18e 100644
--- a/src/app/shared/components/training-type-picker/training-type-picker.component.html
+++ b/src/app/shared/components/training-type-picker/training-type-picker.component.html
@@ -8,11 +8,11 @@
           [indeterminate]="getCategoryCheckboxStatus(category) === 'halfChecked'"
           (action)="pickAllCategory(category); $event.stopPropagation()"
         />
-        <span
+        <label
           class="titleCollapse"
-          id="label-{{ category.id }}"
+          for="{{ category.id }}"
           [attr.aria-label]="category.name + '. Cocher pour tout sélectionner'"
-          >{{ category.name }}</span
+          >{{ category.name }}</label
         >
       </div>
     </app-collapse-header>
diff --git a/src/app/structure-list/components/more-filters/more-filters.component.html b/src/app/structure-list/components/more-filters/more-filters.component.html
index 2820d736f..bda9529a0 100644
--- a/src/app/structure-list/components/more-filters/more-filters.component.html
+++ b/src/app/structure-list/components/more-filters/more-filters.component.html
@@ -38,9 +38,7 @@
               [indeterminate]="getCategoryCheckboxStatus(c) === 'halfChecked'"
               (action)="handleCategoryCheckBox($event, c); $event.stopPropagation()"
             />
-            <span id="label-{{ c.id }}" [attr.aria-label]="c.name + '. Cocher pour tout sélectionner'">{{
-              c.name
-            }}</span>
+            <label for="{{ c.id }}" [attr.aria-label]="c.name + '. Cocher pour tout sélectionner'">{{ c.name }}</label>
           </div>
         </app-collapse-header>
         <app-collapse-content>
-- 
GitLab


From 0e1155ccf05b6431dc0cf9ee3205f59e6d64bc57 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 16:11:50 +0200
Subject: [PATCH 4/8] wip

---
 .../filter-modal/filter-modal.component.html       |  7 ++++++-
 .../more-filters/more-filters.component.html       |  7 ++++++-
 .../structure-list-search.component.ts             | 14 +++++++-------
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/app/annuaire/filter-modal/filter-modal.component.html b/src/app/annuaire/filter-modal/filter-modal.component.html
index 5031c5b06..6798808c8 100644
--- a/src/app/annuaire/filter-modal/filter-modal.component.html
+++ b/src/app/annuaire/filter-modal/filter-modal.component.html
@@ -12,7 +12,12 @@
     </div>
 
     <div class="modalFooter">
-      <app-button [variant]="'secondary'" [label]="'Effacer'" (action)="clearFilters()" />
+      <app-button
+        [variant]="'secondary'"
+        [label]="'Effacer'"
+        [attr.aria-label]="'Effacer et fermer'"
+        (action)="clearFilters()"
+      />
       <app-button [variant]="'primary'" [label]="'Appliquer'" (action)="onSubmitFilters()" />
     </div>
   </div>
diff --git a/src/app/structure-list/components/more-filters/more-filters.component.html b/src/app/structure-list/components/more-filters/more-filters.component.html
index bda9529a0..71f0a0858 100644
--- a/src/app/structure-list/components/more-filters/more-filters.component.html
+++ b/src/app/structure-list/components/more-filters/more-filters.component.html
@@ -56,7 +56,12 @@
       </app-collapse>
     </div>
     <div class="modalFooter">
-      <app-button [variant]="'secondary'" [label]="'Effacer'" (action)="clearFilters()" />
+      <app-button
+        [variant]="'secondary'"
+        [label]="'Effacer'"
+        [attr.aria-label]="'Effacer et fermer'"
+        (action)="clearFilters()"
+      />
       <app-button [variant]="'primary'" [label]="'Appliquer'" (action)="emitModules(checkedModules)" />
     </div>
   </div>
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index a19588e8c..77b01766b 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -177,10 +177,6 @@ export class StructureListSearchComponent implements OnInit {
     // if modal already opened, reset type
     if (this.modalTypeOpened === modalType) {
       this.closeModal();
-      // Accessibility: when navigating with keyboard and closing a filter modal, send focus back to filters
-      if (this.keyboardEvent) {
-        this.setFocusOnFilters();
-      }
     } else if (this.modalTypeOpened !== modalType) {
       this.modalTypeOpened = modalType;
 
@@ -217,15 +213,19 @@ export class StructureListSearchComponent implements OnInit {
 
   private setFocusOnFilters(): void {
     setTimeout(() => {
-      const firstfilter = this.elementRef.nativeElement.querySelector(`.filters button`);
-      if (firstfilter) {
-        const focusedElement = firstfilter as HTMLElement;
+      const firstFilter = this.elementRef.nativeElement.querySelector('.filters button:first-of-type');
+      if (firstFilter) {
+        const focusedElement = firstFilter as HTMLElement;
         focusedElement.focus();
       }
     }, 0);
   }
 
   public closeModal(): void {
+    // Accessibility: when navigating with keyboard and closing a filter modal, send focus back to filters
+    if (this.keyboardEvent) {
+      this.setFocusOnFilters();
+    }
     this.modalTypeOpened = undefined;
   }
 
-- 
GitLab


From 6e4f753ae8618292141bfd94215428d0b47fc694 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 16:31:13 +0200
Subject: [PATCH 5/8] wip

---
 .../structure-list-search.component.html           | 11 ++++++++++-
 .../structure-list-search.component.ts             | 14 +++++++-------
 2 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
index ec9d1c49d..1352ff43e 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
@@ -5,6 +5,7 @@
       <app-collapsable-filter
         [label]="'Démarches en ligne'"
         [expanded]="modalTypeOpened === TypeModal.accompaniment"
+        [id]="'modal' + TypeModal.accompaniment"
         [active]="numberAccompanimentChecked > 0"
         (toggle)="openModal(TypeModal.accompaniment)"
         (keyup)="onKeyboardNavigation($event)"
@@ -12,6 +13,7 @@
       <app-collapsable-filter
         [label]="'Compétences numériques'"
         [expanded]="modalTypeOpened === TypeModal.training"
+        [id]="'modal' + TypeModal.training"
         [active]="numberTrainingChecked > 0"
         (toggle)="openModal(TypeModal.training)"
         (keyup)="onKeyboardNavigation($event)"
@@ -19,6 +21,7 @@
       <app-collapsable-filter
         [label]="'Public'"
         [expanded]="modalTypeOpened === TypeModal.public"
+        [id]="'modal' + TypeModal.public"
         [active]="numberPublicChecked > 0"
         (toggle)="openModal(TypeModal.public)"
         (keyup)="onKeyboardNavigation($event)"
@@ -26,6 +29,7 @@
       <app-collapsable-filter
         [label]="'Matériel & wifi'"
         [expanded]="modalTypeOpened === TypeModal.equipments"
+        [id]="'modal' + TypeModal.equipments"
         [active]="numberEquipmentChecked > 0"
         (toggle)="openModal(TypeModal.equipments)"
         (keyup)="onKeyboardNavigation($event)"
@@ -47,7 +51,12 @@
         [checked]="searchService.getIndex(checkedModulesFilter, 'accesLibre', 'accessModality') > -1"
         (toggle)="externalCheckboxCheck($event)"
       />
-      <app-button [variant]="'tertiary'" [label]="'Plus de filtres'" (action)="openModal(TypeModal.moreFilters)" />
+      <app-button
+        [variant]="'tertiary'"
+        [label]="'Plus de filtres'"
+        [id]="'modal' + TypeModal.moreFilters"
+        (action)="openModal(TypeModal.moreFilters)"
+      />
       <div *ngIf="modalTypeOpened">
         <app-more-filters
           [modalType]="modalTypeOpened"
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index 77b01766b..a8e3d48c2 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -212,13 +212,13 @@ export class StructureListSearchComponent implements OnInit {
   }
 
   private setFocusOnFilters(): void {
-    setTimeout(() => {
-      const firstFilter = this.elementRef.nativeElement.querySelector('.filters button:first-of-type');
-      if (firstFilter) {
-        const focusedElement = firstFilter as HTMLElement;
-        focusedElement.focus();
-      }
-    }, 0);
+    const firstFilter = this.elementRef.nativeElement.querySelector(
+      '#modal' + this.modalTypeOpened + ' button:first-of-type',
+    );
+    if (firstFilter) {
+      const focusedElement = firstFilter as HTMLElement;
+      focusedElement.focus();
+    }
   }
 
   public closeModal(): void {
-- 
GitLab


From 9cd11cc7a21a44ff14ba0d8170881c0faf4b0476 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Thu, 25 Apr 2024 16:41:07 +0200
Subject: [PATCH 6/8] renaming on clarity

---
 .../structure-list-search.component.html             | 10 +++++-----
 .../structure-list-search.component.ts               | 12 ++++++------
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
index 1352ff43e..07de08215 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.html
@@ -8,7 +8,7 @@
         [id]="'modal' + TypeModal.accompaniment"
         [active]="numberAccompanimentChecked > 0"
         (toggle)="openModal(TypeModal.accompaniment)"
-        (keyup)="onKeyboardNavigation($event)"
+        (keyup)="onKeyboardNavOnFilters($event)"
       />
       <app-collapsable-filter
         [label]="'Compétences numériques'"
@@ -16,7 +16,7 @@
         [id]="'modal' + TypeModal.training"
         [active]="numberTrainingChecked > 0"
         (toggle)="openModal(TypeModal.training)"
-        (keyup)="onKeyboardNavigation($event)"
+        (keyup)="onKeyboardNavOnFilters($event)"
       />
       <app-collapsable-filter
         [label]="'Public'"
@@ -24,7 +24,7 @@
         [id]="'modal' + TypeModal.public"
         [active]="numberPublicChecked > 0"
         (toggle)="openModal(TypeModal.public)"
-        (keyup)="onKeyboardNavigation($event)"
+        (keyup)="onKeyboardNavOnFilters($event)"
       />
       <app-collapsable-filter
         [label]="'Matériel & wifi'"
@@ -32,7 +32,7 @@
         [id]="'modal' + TypeModal.equipments"
         [active]="numberEquipmentChecked > 0"
         (toggle)="openModal(TypeModal.equipments)"
-        (keyup)="onKeyboardNavigation($event)"
+        (keyup)="onKeyboardNavOnFilters($event)"
       />
       <app-checkbox-filter
         [module]="{
@@ -64,7 +64,7 @@
           [modules]="checkedModulesFilter"
           (searchEvent)="fetchResults($event)"
           (closeEvent)="closeModal()"
-          (keyup)="onKeyboardNavigation($event)"
+          (keyup)="onKeyboardNavOnFilters($event)"
         />
       </div>
     </div>
diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index a8e3d48c2..d3b3e0024 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -189,7 +189,7 @@ export class StructureListSearchComponent implements OnInit {
 
   // When filters and their modal are in the same component, we can remove onKeyboardNavigation, setFocusOnOpenedModal, and setFocusOnFilters.
   // because the focus will then flow normally between the filter and the modal
-  public onKeyboardNavigation(event: KeyboardEvent): void {
+  public onKeyboardNavOnFilters(event: KeyboardEvent): void {
     switch (event.key) {
       case 'ArrowUp':
       case 'ArrowDown':
@@ -211,12 +211,12 @@ export class StructureListSearchComponent implements OnInit {
     }, 0);
   }
 
-  private setFocusOnFilters(): void {
-    const firstFilter = this.elementRef.nativeElement.querySelector(
+  private setFocusOnFilter(): void {
+    const filterButton = this.elementRef.nativeElement.querySelector(
       '#modal' + this.modalTypeOpened + ' button:first-of-type',
     );
-    if (firstFilter) {
-      const focusedElement = firstFilter as HTMLElement;
+    if (filterButton) {
+      const focusedElement = filterButton as HTMLElement;
       focusedElement.focus();
     }
   }
@@ -224,7 +224,7 @@ export class StructureListSearchComponent implements OnInit {
   public closeModal(): void {
     // Accessibility: when navigating with keyboard and closing a filter modal, send focus back to filters
     if (this.keyboardEvent) {
-      this.setFocusOnFilters();
+      this.setFocusOnFilter();
     }
     this.modalTypeOpened = undefined;
   }
-- 
GitLab


From afdd08f345e13e4943acefb9dfd6b9d14e7a6475 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Mon, 29 Apr 2024 10:53:16 +0200
Subject: [PATCH 7/8] update comment

---
 .../structure-list-search/structure-list-search.component.ts    | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
index d3b3e0024..15dbc16db 100644
--- a/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
+++ b/src/app/structure-list/components/structure-list-search/structure-list-search.component.ts
@@ -187,7 +187,7 @@ export class StructureListSearchComponent implements OnInit {
     }
   }
 
-  // When filters and their modal are in the same component, we can remove onKeyboardNavigation, setFocusOnOpenedModal, and setFocusOnFilters.
+  // When filters and their modal are in the same component, we can remove onKeyboardNavOnFilters, setFocusOnOpenedModal, and setFocusOnFilters.
   // because the focus will then flow normally between the filter and the modal
   public onKeyboardNavOnFilters(event: KeyboardEvent): void {
     switch (event.key) {
-- 
GitLab


From f67d8b791825eb06deae30652347493c1eb48108 Mon Sep 17 00:00:00 2001
From: Marlene Simondant <msimondant@grandlyon.com>
Date: Mon, 29 Apr 2024 11:02:08 +0200
Subject: [PATCH 8/8] fix aria label buttons

---
 src/app/annuaire/filter-modal/filter-modal.component.html       | 2 +-
 .../components/more-filters/more-filters.component.html         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/app/annuaire/filter-modal/filter-modal.component.html b/src/app/annuaire/filter-modal/filter-modal.component.html
index 6798808c8..56163e779 100644
--- a/src/app/annuaire/filter-modal/filter-modal.component.html
+++ b/src/app/annuaire/filter-modal/filter-modal.component.html
@@ -15,7 +15,7 @@
       <app-button
         [variant]="'secondary'"
         [label]="'Effacer'"
-        [attr.aria-label]="'Effacer et fermer'"
+        [ariaLabel]="'Effacer et fermer'"
         (action)="clearFilters()"
       />
       <app-button [variant]="'primary'" [label]="'Appliquer'" (action)="onSubmitFilters()" />
diff --git a/src/app/structure-list/components/more-filters/more-filters.component.html b/src/app/structure-list/components/more-filters/more-filters.component.html
index 71f0a0858..8c8dd97c7 100644
--- a/src/app/structure-list/components/more-filters/more-filters.component.html
+++ b/src/app/structure-list/components/more-filters/more-filters.component.html
@@ -59,7 +59,7 @@
       <app-button
         [variant]="'secondary'"
         [label]="'Effacer'"
-        [attr.aria-label]="'Effacer et fermer'"
+        [ariaLabel]="'Effacer et fermer'"
         (action)="clearFilters()"
       />
       <app-button [variant]="'primary'" [label]="'Appliquer'" (action)="emitModules(checkedModules)" />
-- 
GitLab