From 3335f6421d8f1f139677f8c72e29fb5001accc9e Mon Sep 17 00:00:00 2001
From: OZGCloud <ozgcloud@mgm-tp.com>
Date: Mon, 2 Sep 2024 13:04:44 +0200
Subject: [PATCH] OZG-6103 OZG-6631 Fix popup list focus

---
 .../lib/popup/popup/popup.component.spec.ts   | 42 ++++++++++++++++++-
 .../src/lib/popup/popup/popup.component.ts    | 17 ++++++--
 2 files changed, 55 insertions(+), 4 deletions(-)

diff --git a/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.spec.ts b/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.spec.ts
index 8d03abd239..fe6160acf3 100644
--- a/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.spec.ts
+++ b/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.spec.ts
@@ -1,5 +1,5 @@
 import { getElementFromFixture } from '@alfa-client/test-utils';
-import { ComponentFixture, TestBed } from '@angular/core/testing';
+import { ComponentFixture, fakeAsync, TestBed, tick } from '@angular/core/testing';
 import { getDataTestIdOf } from 'libs/tech-shared/test/data-test';
 import { PopupComponent } from './popup.component';
 
@@ -40,6 +40,46 @@ describe('PopupComponent', () => {
     });
   });
 
+  describe('handleButtonClick', () => {
+    beforeEach(() => {
+      component.togglePopup = jest.fn();
+      component.focusList = jest.fn();
+    });
+
+    it('should toggle popup', () => {
+      component.handleButtonClick();
+
+      expect(component.togglePopup).toHaveBeenCalled();
+    });
+
+    it('should focus list if popup is visible', () => {
+      component.isPopupOpen = true;
+
+      component.handleButtonClick();
+
+      expect(component.focusList).toHaveBeenCalled();
+    });
+
+    it('should not focus list if popup is hidden', () => {
+      component.handleButtonClick();
+
+      expect(component.focusList).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('focusList', () => {
+    it('should focus popup list item', fakeAsync(() => {
+      component.isPopupOpen = true;
+      fixture.detectChanges();
+      component.popupListRef.nativeElement.focus = jest.fn();
+
+      component.focusList();
+      tick();
+
+      expect(component.popupListRef.nativeElement.focus).toHaveBeenCalled();
+    }));
+  });
+
   describe('aria-expanded', () => {
     it('should be true if popup is open', () => {
       component.isPopupOpen = true;
diff --git a/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.ts b/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.ts
index 0a92ee71d3..171397997f 100644
--- a/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.ts
+++ b/alfa-client/libs/design-system/src/lib/popup/popup/popup.component.ts
@@ -10,7 +10,7 @@ import { twMerge } from 'tailwind-merge';
   template: `<div class="relative w-fit">
     <button
       [ngClass]="[twMerge('w-fit outline-2 outline-offset-2 outline-focus', buttonClass)]"
-      (click)="togglePopup()"
+      (click)="handleButtonClick()"
       [attr.aria-expanded]="isPopupOpen"
       aria-haspopup="true"
       [attr.aria-label]="label"
@@ -25,8 +25,9 @@ import { twMerge } from 'tailwind-merge';
       [ngClass]="alignTo === 'left' ? 'right-0' : 'left-0'"
       role="dialog"
       aria-modal="true"
+      tabIndex="-1"
       cdkTrapFocus
-      [cdkTrapFocusAutoCapture]="true"
+      #popupList
     >
       <ng-content />
     </ul>
@@ -38,9 +39,10 @@ export class PopupComponent {
   @Input() buttonClass: string = '';
 
   isPopupOpen: boolean = false;
-  twMerge = twMerge;
+  readonly twMerge = twMerge;
 
   @ViewChild('button') buttonRef: ElementRef<HTMLButtonElement>;
+  @ViewChild('popupList') popupListRef: ElementRef<HTMLUListElement>;
 
   @HostListener('document:keydown', ['$event'])
   onKeydownHandler(e: KeyboardEvent): void {
@@ -56,6 +58,15 @@ export class PopupComponent {
     }
   }
 
+  handleButtonClick(): void {
+    this.togglePopup();
+    if (this.isPopupOpen) this.focusList();
+  }
+
+  focusList(): void {
+    setTimeout(() => this.popupListRef.nativeElement.focus());
+  }
+
   togglePopup(): void {
     this.isPopupOpen = !this.isPopupOpen;
   }
-- 
GitLab