diff --git a/change/@ni-nimble-components-4d32fe1a-efcc-4f03-b069-09a00bd0bc3d.json b/change/@ni-nimble-components-4d32fe1a-efcc-4f03-b069-09a00bd0bc3d.json new file mode 100644 index 0000000000..e718823d7d --- /dev/null +++ b/change/@ni-nimble-components-4d32fe1a-efcc-4f03-b069-09a00bd0bc3d.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Fix race condition when closing the drawer immediately after it finishes opening", + "packageName": "@ni/nimble-components", + "email": "20542556+mollykreis@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/nimble-components/src/drawer/index.ts b/packages/nimble-components/src/drawer/index.ts index 45306082c4..ea1c8d83b2 100644 --- a/packages/nimble-components/src/drawer/index.ts +++ b/packages/nimble-components/src/drawer/index.ts @@ -131,6 +131,13 @@ export class Drawer extends FoundationElement { } private triggerAnimation(): void { + // Read the offsetHeight of the dialog to trigger a reflow. This guarantees that the browser + // has processed the 'animating' class being removed before trying to readd it, even if the previous + // animation has just finished. Otherwise, problems can occur. For example, trying to close the + // drawer immediately after the opening animation ends does not actually close the drawer. + // https://github.com/ni/nimble/issues/1994 + void this.dialog.offsetHeight; + this.dialog.classList.add('animating'); if (this.closing) { this.dialog.classList.add('closing'); diff --git a/packages/nimble-components/src/drawer/tests/drawer.spec.ts b/packages/nimble-components/src/drawer/tests/drawer.spec.ts index eefa3b0f52..632820c834 100644 --- a/packages/nimble-components/src/drawer/tests/drawer.spec.ts +++ b/packages/nimble-components/src/drawer/tests/drawer.spec.ts @@ -133,8 +133,7 @@ describe('Drawer', () => { await expectAsync(promise).toBePending(); }); - // Firefox skipped, see: https://github.com/ni/nimble/issues/1937 - it('should resolve promise if drawer completely opens before being closed #SkipFirefox', async () => { + it('should resolve promise if drawer completely opens before being closed', async () => { const promise = element.show(); await completeAnimationAsync(element); element.close();