From 106d346d72568f8256a942478d808d002f5421c7 Mon Sep 17 00:00:00 2001 From: Artur Androsovych Date: Thu, 21 Apr 2022 06:16:46 +0300 Subject: [PATCH] perf(module:modal): call `focus()` on the next rendering frame to prevent frame drop (#7293) Calling `focus()` on the element causes browsers to do re-layouts. This can been seen here: https://gist.github.com/paulirish/5d52fb081b3570c81e3a#setting-focus Microtasks are executed asynchronously, but within the current rendering frame. Using `requestAnimationFrame` except of `Promise.resolve` basically unloads the current frame and calls `focus()` on the next rendering frame, this prevent frame drops on slower devices when the modal is opened. --- components/modal/modal-container.directive.ts | 3 ++- components/modal/modal.spec.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/components/modal/modal-container.directive.ts b/components/modal/modal-container.directive.ts index a81199b40a3..62aa195dc15 100644 --- a/components/modal/modal-container.directive.ts +++ b/components/modal/modal-container.directive.ts @@ -23,6 +23,7 @@ import { fromEvent, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { NzConfigService } from 'ng-zorro-antd/core/config'; +import { reqAnimFrame } from 'ng-zorro-antd/core/polyfill'; import { NzSafeAny } from 'ng-zorro-antd/core/types'; import { getElementOffset, isNotNil } from 'ng-zorro-antd/core/util'; @@ -157,7 +158,7 @@ export class BaseModalContainerComponent extends BasePortalOutlet implements OnD if (this.document) { this.elementFocusedBeforeModalWasOpened = this.document.activeElement as HTMLElement; if (this.host.nativeElement.focus) { - this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => this.host.nativeElement.focus())); + this.ngZone.runOutsideAngular(() => reqAnimFrame(() => this.host.nativeElement.focus())); } } } diff --git a/components/modal/modal.spec.ts b/components/modal/modal.spec.ts index fc92498fdf3..83fba4f96df 100644 --- a/components/modal/modal.spec.ts +++ b/components/modal/modal.spec.ts @@ -1121,7 +1121,7 @@ describe('NzModal', () => { }); fixture.detectChanges(); - flushMicrotasks(); + tick(16); expect(document.activeElement!.tagName).toBe('NZ-MODAL-CONTAINER', 'Expected modal container to be focused.'); }));