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 - - - -``` - -
-```` +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 + + + +```