Skip to content
5 changes: 0 additions & 5 deletions core/src/components/modal/modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import { Style as StatusBarStyle, StatusBar } from '@utils/native/status-bar';
import {
GESTURE,
BACKDROP,
activeAnimations,
dismiss,
eventMethod,
prepareOverlay,
Expand Down Expand Up @@ -705,8 +704,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
this.keyboardOpenCallback = undefined;
}

const enteringAnimation = activeAnimations.get(this) || [];

const dismissed = await dismiss<ModalDismissOptions>(
this,
data,
Expand All @@ -733,8 +730,6 @@ export class Modal implements ComponentInterface, OverlayInterface {
if (this.gesture) {
this.gesture.destroy();
}

enteringAnimation.forEach((ani) => ani.destroy());
}
this.currentBreakpoint = undefined;
this.animation = undefined;
Expand Down
45 changes: 45 additions & 0 deletions core/src/components/modal/test/animations/modal.e2e.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';

configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ config, title }) => {
test.describe(title('modal: animations'), () => {
test.beforeEach(async ({ page }) => {
await page.setContent(
`
<ion-modal is-open="true" trigger="open-modal"></ion-modal>
`,
config
);
});
test('card modal should clean up animations on dismiss', async ({ page }, testInfo) => {
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/28352',
});

const ionModalDidDismiss = await page.spyOnEvent('ionModalDidDismiss');

const modal = page.locator('ion-modal');

const initialAnimations = await modal.evaluate((el: HTMLIonModalElement) => {
return el.shadowRoot!.getAnimations();
});

// While the modal is open, it should have animations
expect(initialAnimations.length).toBeGreaterThan(0);

await modal.evaluate((el: HTMLIonModalElement) => {
el.dismiss();
});

await ionModalDidDismiss.next();

const currentAnimations = await modal.evaluate((el: HTMLIonModalElement) => {
return el.shadowRoot!.getAnimations();
});

// Once the modal has finished closing, there should be no animations
expect(currentAnimations.length).toBe(0);
});
});
});
6 changes: 6 additions & 0 deletions core/src/utils/overlays.ts
Original file line number Diff line number Diff line change
Expand Up @@ -577,6 +577,12 @@ export const dismiss = async <OverlayDismissOptions>(
overlay.didDismiss.emit({ data, role });
overlay.didDismissShorthand?.emit({ data, role });

// Get a reference to all animations currently assigned to this overlay
// Then tear them down to return the overlay to its initial visual state
const animations = activeAnimations.get(overlay) || [];

animations.forEach((ani) => ani.destroy());

activeAnimations.delete(overlay);

/**
Expand Down