Skip to content

Commit 96c5e41

Browse files
committed
feat(modal): add contentAnimation support and animateContentHeight option
1 parent 1dcf5c9 commit 96c5e41

File tree

6 files changed

+43
-29
lines changed

6 files changed

+43
-29
lines changed

core/src/components/modal/animations/ios.enter.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,33 @@ const createEnterAnimation = () => {
1717

1818
const wrapperAnimation = createAnimation().fromTo('transform', 'translateY(100vh)', 'translateY(0vh)');
1919

20-
return { backdropAnimation, wrapperAnimation };
20+
return { backdropAnimation, wrapperAnimation, contentAnimation: undefined };
2121
};
2222

2323
/**
2424
* iOS Modal Enter Animation for the Card presentation style
2525
*/
2626
export const iosEnterAnimation = (baseEl: HTMLElement, opts: ModalAnimationOptions): Animation => {
27-
const { presentingEl, currentBreakpoint } = opts;
27+
const { presentingEl, currentBreakpoint, animateContentHeight } = opts;
2828
const root = getElementRoot(baseEl);
29-
const { wrapperAnimation, backdropAnimation } =
29+
const { wrapperAnimation, backdropAnimation, contentAnimation } =
3030
currentBreakpoint !== undefined ? createSheetEnterAnimation(opts) : createEnterAnimation();
3131

3232
backdropAnimation.addElement(root.querySelector('ion-backdrop')!);
3333

3434
wrapperAnimation.addElement(root.querySelectorAll('.modal-wrapper, .modal-shadow')!).beforeStyles({ opacity: 1 });
3535

36+
contentAnimation?.addElement(baseEl.querySelector('.ion-page')!);
37+
3638
const baseAnimation = createAnimation('entering-base')
3739
.addElement(baseEl)
3840
.easing('cubic-bezier(0.32,0.72,0,1)')
3941
.duration(500)
40-
.addAnimation(wrapperAnimation);
42+
.addAnimation([wrapperAnimation]);
43+
44+
if (contentAnimation && animateContentHeight) {
45+
baseAnimation.addAnimation(contentAnimation);
46+
}
4147

4248
if (presentingEl) {
4349
const isMobile = window.innerWidth < 768;

core/src/components/modal/animations/md.enter.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,33 @@ const createEnterAnimation = () => {
1919
{ offset: 1, opacity: 1, transform: `translateY(0px)` },
2020
]);
2121

22-
return { backdropAnimation, wrapperAnimation };
22+
return { backdropAnimation, wrapperAnimation, contentAnimation: undefined };
2323
};
2424

2525
/**
2626
* Md Modal Enter Animation
2727
*/
2828
export const mdEnterAnimation = (baseEl: HTMLElement, opts: ModalAnimationOptions): Animation => {
29-
const { currentBreakpoint } = opts;
29+
const { currentBreakpoint, animateContentHeight } = opts;
3030
const root = getElementRoot(baseEl);
31-
const { wrapperAnimation, backdropAnimation } =
31+
const { wrapperAnimation, backdropAnimation, contentAnimation } =
3232
currentBreakpoint !== undefined ? createSheetEnterAnimation(opts) : createEnterAnimation();
3333

3434
backdropAnimation.addElement(root.querySelector('ion-backdrop')!);
3535

3636
wrapperAnimation.addElement(root.querySelector('.modal-wrapper')!);
3737

38-
return createAnimation()
39-
.addElement(baseEl)
40-
.easing('cubic-bezier(0.36,0.66,0.04,1)')
41-
.duration(280)
42-
.addAnimation([backdropAnimation, wrapperAnimation]);
38+
contentAnimation?.addElement(baseEl.querySelector('.ion-page')!);
39+
40+
const baseAnimation = createAnimation()
41+
.addElement(baseEl)
42+
.easing('cubic-bezier(0.36,0.66,0.04,1)')
43+
.duration(280)
44+
.addAnimation([backdropAnimation, wrapperAnimation]);
45+
46+
if (contentAnimation && animateContentHeight) {
47+
baseAnimation.addAnimation(contentAnimation);
48+
}
49+
50+
return baseAnimation;
4351
};

core/src/components/modal/animations/sheet.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,12 @@ export const createSheetEnterAnimation = (opts: ModalAnimationOptions) => {
2929
{ offset: 1, opacity: 1, transform: `translateY(${100 - currentBreakpoint! * 100}%)` },
3030
]);
3131

32-
return { wrapperAnimation, backdropAnimation };
32+
const contentAnimation = createAnimation('contentAnimation').keyframes([
33+
{ offset: 0, opacity: 1, maxHeight: `${(1 - currentBreakpoint!) * 100}%` },
34+
{ offset: 1, opacity: 1, maxHeight: `${currentBreakpoint! * 100}%` },
35+
]);
36+
37+
return { wrapperAnimation, backdropAnimation, contentAnimation };
3338
};
3439

3540
export const createSheetLeaveAnimation = (opts: ModalAnimationOptions) => {

core/src/components/modal/gestures/sheet.ts

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { createAnimation } from '@utils/animation/animation';
21
import { isIonContent, findClosestIonContent } from '@utils/content';
32
import { createGesture } from '@utils/gesture';
43
import { clamp, raf, getElementRoot } from '@utils/helpers';
@@ -89,21 +88,7 @@ export const createSheetGesture = (
8988
const minBreakpoint = breakpoints[0];
9089
const wrapperAnimation = animation.childAnimations.find((ani) => ani.id === 'wrapperAnimation');
9190
const backdropAnimation = animation.childAnimations.find((ani) => ani.id === 'backdropAnimation');
92-
let contentAnimation: Animation | undefined;
93-
if (!scrollAtEdge) {
94-
/**
95-
* If scrollAtEdge is disabled, the content should be scrollable
96-
* at any breakpoint and the maxHeight animated so the content is
97-
* fully viewable at any breakpoint.
98-
*/
99-
contentAnimation = animation
100-
.addAnimation(
101-
createAnimation('contentAnimation')
102-
.addElement(contentEl!.parentElement!)
103-
.keyframes(SheetDefaults.CONTENT_KEYFRAMES)
104-
)
105-
.childAnimations.find((ani) => ani.id === 'contentAnimation');
106-
}
91+
const contentAnimation = animation.childAnimations.find((ani) => ani.id === 'contentAnimation');
10792

10893
const enableBackdrop = () => {
10994
baseEl.style.setProperty('pointer-events', 'auto');
@@ -142,6 +127,7 @@ export const createSheetGesture = (
142127
if (wrapperAnimation && backdropAnimation) {
143128
wrapperAnimation.keyframes([...SheetDefaults.WRAPPER_KEYFRAMES]);
144129
backdropAnimation.keyframes([...SheetDefaults.BACKDROP_KEYFRAMES]);
130+
contentAnimation?.keyframes([...SheetDefaults.CONTENT_KEYFRAMES]);
145131
animation.progressStart(true, 1 - currentBreakpoint);
146132

147133
/**

core/src/components/modal/modal-interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ export interface ModalAnimationOptions {
3131
presentingEl?: HTMLElement;
3232
currentBreakpoint?: number;
3333
backdropBreakpoint?: number;
34+
animateContentHeight?: boolean;
3435
}
3536

3637
export interface ModalBreakpointChangeEventDetail {

core/src/components/modal/modal.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
573573
presentingEl: presentingElement,
574574
currentBreakpoint: this.initialBreakpoint,
575575
backdropBreakpoint: this.backdropBreakpoint,
576+
animateContentHeight: !this.scrollAtEdge
576577
});
577578

578579
/* tslint:disable-next-line */
@@ -679,6 +680,7 @@ export class Modal implements ComponentInterface, OverlayInterface {
679680
presentingEl: this.presentingElement,
680681
currentBreakpoint: initialBreakpoint,
681682
backdropBreakpoint,
683+
animateContentHeight: !this.scrollAtEdge,
682684
}));
683685

684686
ani.progressStart(true, 1);
@@ -1031,6 +1033,12 @@ interface ModalOverlayOptions {
10311033
* to fade in when using a sheet modal.
10321034
*/
10331035
backdropBreakpoint: number;
1036+
1037+
/**
1038+
* Whether or not the modal should animate
1039+
* content's max-height.
1040+
*/
1041+
animateContentHeight?: boolean;
10341042
}
10351043

10361044
type ModalPresentOptions = ModalOverlayOptions;

0 commit comments

Comments
 (0)