diff --git a/docs/utilities/animations.md b/docs/utilities/animations.md
index 92c6eebc67a..d53bfbca0e5 100644
--- a/docs/utilities/animations.md
+++ b/docs/utilities/animations.md
@@ -1279,236 +1279,9 @@ Certain Ionic components allow developers to provide custom animations. All anim
### Modals
-````mdx-code-block
-
-
-
-```javascript
-customElements.define('modal-page', class extends HTMLElement {
- connectedCallback() {
- this.innerHTML = `
-
-
- Modal Header
-
-
-
- Modal Content
-
- `;
- }
-});
-
-function presentModal() {
- const enterAnimation = (baseEl: any) => {
- const root = baseEl.shadowRoot;
-
- const backdropAnimation = createAnimation()
- .addElement(root.querySelector('ion-backdrop')!)
- .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
-
- const wrapperAnimation = createAnimation()
- .addElement(root.querySelector('.modal-wrapper')!)
- .keyframes([
- { offset: 0, opacity: '0', transform: 'scale(0)' },
- { offset: 1, opacity: '0.99', transform: 'scale(1)' }
- ]);
-
- return createAnimation()
- .addElement(baseEl)
- .easing('ease-out')
- .duration(500)
- .addAnimation([backdropAnimation, wrapperAnimation]);
- }
-
- const leaveAnimation = (baseEl: any) => {
- return enterAnimation(baseEl).direction('reverse');
- }
-
- // create the modal with the `modal-page` component
- const modalElement = document.createElement('ion-modal');
- modalElement.component = 'modal-page';
- modalElement.enterAnimation = enterAnimation;
- modalElement.leaveAnimation = leaveAnimation;
-
- // present the modal
- document.body.appendChild(modalElement);
- return modalElement.present();
-}
-```
-
-
-
-```tsx
-import { Component } from '@angular/core';
-import { ModalController, AnimationController } from '@ionic/angular';
-import { ModalPage } from '../modal/modal.page';
-
-@Component({
- selector: 'modal-example',
- templateUrl: 'modal-example.html',
- styleUrls: ['./modal-example.css']
-})
-export class ModalExample {
- constructor(public modalController: ModalController,
- public animationCtrl: AnimationController) { }
-
- async presentModal() {
- const enterAnimation = (baseEl: any) => {
- const root = baseEl.shadowRoot;
-
- const backdropAnimation = this.animationCtrl.create()
- .addElement(root.querySelector('ion-backdrop')!)
- .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
-
- const wrapperAnimation = this.animationCtrl.create()
- .addElement(root.querySelector('.modal-wrapper')!)
- .keyframes([
- { offset: 0, opacity: '0', transform: 'scale(0)' },
- { offset: 1, opacity: '0.99', transform: 'scale(1)' }
- ]);
-
- return this.animationCtrl.create()
- .addElement(baseEl)
- .easing('ease-out')
- .duration(500)
- .addAnimation([backdropAnimation, wrapperAnimation]);
- }
-
- const leaveAnimation = (baseEl: any) => {
- return enterAnimation(baseEl).direction('reverse');
- }
-
- const modal = await this.modalController.create({
- component: ModalPage,
- enterAnimation,
- leaveAnimation
- });
- return await modal.present();
- }
-}
-```
-
-
-
-```jsx
-import React, { useState } from 'react';
-import { createAnimation, IonModal, IonButton, IonContent } from '@ionic/react';
-
-export const ModalExample: React.FC = () => {
- const [showModal, setShowModal] = useState(false);
-
- const enterAnimation = (baseEl: any) => {
- const root = baseEl.shadowRoot;
-
- const backdropAnimation = createAnimation()
- .addElement(root.querySelector('ion-backdrop')!)
- .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
-
- const wrapperAnimation = createAnimation()
- .addElement(root.querySelector('.modal-wrapper')!)
- .keyframes([
- { offset: 0, opacity: '0', transform: 'scale(0)' },
- { offset: 1, opacity: '0.99', transform: 'scale(1)' }
- ]);
-
- return createAnimation()
- .addElement(baseEl)
- .easing('ease-out')
- .duration(500)
- .addAnimation([backdropAnimation, wrapperAnimation]);
- }
-
- const leaveAnimation = (baseEl: any) => {
- return enterAnimation(baseEl).direction('reverse');
- }
-
- return (
-
-
- This is modal content
- setShowModal(false)}>Close Modal
-
- setShowModal(true)}>Show Modal
-
- );
-};
-```
-
-
-
-```jsx
-
-
-
-
- Modal content goes here.
-
-
- Show Modal
-
-
-
-
-
-```
-
-
-````
+import ModalOverride from '@site/static/usage/v7/animations/modal-override/index.md';
-
+
## Performance Considerations
diff --git a/static/code/stackblitz/v7/html/index.ts b/static/code/stackblitz/v7/html/index.ts
index 952785602e6..c820961c828 100644
--- a/static/code/stackblitz/v7/html/index.ts
+++ b/static/code/stackblitz/v7/html/index.ts
@@ -1,6 +1,6 @@
import { defineCustomElements } from '@ionic/core/loader';
-import { loadingController, modalController, pickerController, toastController } from '@ionic/core';
+import { createAnimation, loadingController, modalController, pickerController, toastController } from '@ionic/core';
/* Core CSS required for Ionic components to work properly */
import '@ionic/core/css/core.css';
@@ -27,3 +27,4 @@ defineCustomElements();
(window as any).modalController = modalController;
(window as any).pickerController = pickerController;
(window as any).toastController = toastController;
+(window as any).createAnimation = createAnimation;
diff --git a/static/usage/v7/animations/modal-override/angular/example_component_html.md b/static/usage/v7/animations/modal-override/angular/example_component_html.md
new file mode 100644
index 00000000000..178ae34c17b
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/angular/example_component_html.md
@@ -0,0 +1,23 @@
+```html
+
+
+ Page
+
+
+
+ Present Modal
+
+
+
+
+ Modal
+
+ Close
+
+
+
+ Modal Content
+
+
+
+```
diff --git a/static/usage/v7/animations/modal-override/angular/example_component_ts.md b/static/usage/v7/animations/modal-override/angular/example_component_ts.md
new file mode 100644
index 00000000000..b1fe997c1d4
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/angular/example_component_ts.md
@@ -0,0 +1,52 @@
+```ts
+import { Component, ViewChild } from '@angular/core';
+import type { IonModal } from '@ionic/angular';
+import { AnimationController } from '@ionic/angular';
+
+@Component({
+ selector: 'app-example',
+ templateUrl: 'example.component.html',
+})
+export class ExampleComponent {
+ @ViewChild('modal', { static: true }) modal: IonModal;
+
+ constructor(private animationCtrl: AnimationController) {}
+
+ ngOnInit() {
+ const enterAnimation = (baseEl: HTMLElement) => {
+ const root = baseEl.shadowRoot;
+
+ const backdropAnimation = this.animationCtrl
+ .create()
+ .addElement(root.querySelector('ion-backdrop'))
+ .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
+
+ const wrapperAnimation = this.animationCtrl
+ .create()
+ .addElement(root.querySelector('.modal-wrapper'))
+ .keyframes([
+ { offset: 0, opacity: '0', transform: 'scale(0)' },
+ { offset: 1, opacity: '0.99', transform: 'scale(1)' },
+ ]);
+
+ return this.animationCtrl
+ .create()
+ .addElement(baseEl)
+ .easing('ease-out')
+ .duration(500)
+ .addAnimation([backdropAnimation, wrapperAnimation]);
+ };
+
+ const leaveAnimation = (baseEl: HTMLElement) => {
+ return enterAnimation(baseEl).direction('reverse');
+ };
+
+ this.modal.enterAnimation = enterAnimation;
+ this.modal.leaveAnimation = leaveAnimation;
+ }
+
+ closeModal() {
+ this.modal.dismiss();
+ }
+}
+```
diff --git a/static/usage/v7/animations/modal-override/demo.html b/static/usage/v7/animations/modal-override/demo.html
new file mode 100644
index 00000000000..15da72756db
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/demo.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+ Accordion
+
+
+
+
+
+
+
+
+
+
+
+ Page
+
+
+
+
+ Present Modal
+
+
+
+ Modal
+
+ Close
+
+
+
+ Modal Content
+
+
+
+
+
+
+
+
diff --git a/static/usage/v7/animations/modal-override/index.md b/static/usage/v7/animations/modal-override/index.md
new file mode 100644
index 00000000000..ba289f42c62
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/index.md
@@ -0,0 +1,26 @@
+import Playground from '@site/src/components/global/Playground';
+
+import javascript from './javascript.md';
+import react from './react.md';
+import vue from './vue.md';
+
+import angular_example_component_html from './angular/example_component_html.md';
+import angular_example_component_ts from './angular/example_component_ts.md';
+
+
diff --git a/static/usage/v7/animations/modal-override/javascript.md b/static/usage/v7/animations/modal-override/javascript.md
new file mode 100644
index 00000000000..0efad523d3b
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/javascript.md
@@ -0,0 +1,57 @@
+```html
+
+
+ Page
+
+
+
+ Present Modal
+
+
+
+ Modal
+
+ Close
+
+
+
+ Modal Content
+
+
+
+
+```
diff --git a/static/usage/v7/animations/modal-override/react.md b/static/usage/v7/animations/modal-override/react.md
new file mode 100644
index 00000000000..730881c49a9
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/react.md
@@ -0,0 +1,71 @@
+```tsx
+import React, { useRef } from 'react';
+import {
+ IonButton,
+ IonButtons,
+ IonContent,
+ IonHeader,
+ IonModal,
+ IonToolbar,
+ IonTitle,
+ createAnimation,
+} from '@ionic/react';
+
+function Example() {
+ const modalEl = useRef(null);
+
+ const enterAnimation = (baseEl: HTMLElement) => {
+ const root = baseEl.shadowRoot!;
+
+ const backdropAnimation = createAnimation()
+ .addElement(root.querySelector('ion-backdrop')!)
+ .fromTo('opacity', '0.01', 'var(--backdrop-opacity)');
+
+ const wrapperAnimation = createAnimation()
+ .addElement(root.querySelector('.modal-wrapper')!)
+ .keyframes([
+ { offset: 0, opacity: '0', transform: 'scale(0)' },
+ { offset: 1, opacity: '0.99', transform: 'scale(1)' },
+ ]);
+
+ return createAnimation()
+ .addElement(baseEl)
+ .easing('ease-out')
+ .duration(500)
+ .addAnimation([backdropAnimation, wrapperAnimation]);
+ };
+
+ const leaveAnimation = (baseEl: HTMLElement) => {
+ return enterAnimation(baseEl).direction('reverse');
+ };
+
+ const closeModal = () => {
+ modalEl.current?.dismiss();
+ };
+
+ return (
+ <>
+
+
+ Page
+
+
+
+ Present Modal
+
+
+
+ Modal
+
+ Close
+
+
+
+ Modal Content
+
+
+ >
+ );
+}
+export default Example;
+```
diff --git a/static/usage/v7/animations/modal-override/vue.md b/static/usage/v7/animations/modal-override/vue.md
new file mode 100644
index 00000000000..82c05ba66e6
--- /dev/null
+++ b/static/usage/v7/animations/modal-override/vue.md
@@ -0,0 +1,90 @@
+```html
+
+
+
+ Page
+
+
+
+ Present Modal
+
+
+
+ Modal
+
+ Close
+
+
+
+ Modal Content
+
+
+
+
+
+```