mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 10:41:13 +08:00
fix(modal): account for safe area on devices with a notch (#20072)
* fix card modal on notch phones * only apply safe area for card modal * fix styles, fix gesture race condition * a few more tweaks
This commit is contained in:

committed by
Liam DeBeasi

parent
9d1fe2e14f
commit
1cabb53650
@ -27,14 +27,15 @@ export const iosEnterAnimation = (
|
||||
.addAnimation([backdropAnimation, wrapperAnimation]);
|
||||
|
||||
if (presentingEl) {
|
||||
const modalTransform = (presentingEl.tagName === 'ION-MODAL' && (presentingEl as HTMLIonModalElement).presentingElement !== undefined) ? 40 : 0;
|
||||
const modalTransform = (presentingEl.tagName === 'ION-MODAL' && (presentingEl as HTMLIonModalElement).presentingElement !== undefined) ? '-10px' : 'calc(var(--ion-safe-area-top) + 10px)';
|
||||
const bodyEl = document.body;
|
||||
const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
||||
const finalTransform = `translateY(${-modalTransform}px) scale(${toPresentingScale})`;
|
||||
const finalTransform = `translateY(${modalTransform}) scale(${toPresentingScale})`;
|
||||
|
||||
const presentingAnimation = createAnimation()
|
||||
.beforeStyles({
|
||||
'transform': 'translateY(0)'
|
||||
'transform': 'translateY(0)',
|
||||
'transform-origin': 'top center'
|
||||
})
|
||||
.afterStyles({
|
||||
'transform': finalTransform
|
||||
|
@ -18,7 +18,7 @@ export const iosLeaveAnimation = (
|
||||
const wrapperAnimation = createAnimation()
|
||||
.addElement(baseEl.querySelector('.modal-wrapper')!)
|
||||
.beforeStyles({ 'opacity': 1 })
|
||||
.fromTo('transform', `translateY(0%)`, 'translateY(100%)');
|
||||
.fromTo('transform', 'translateY(0%)', 'translateY(100%)');
|
||||
|
||||
const baseAnimation = createAnimation()
|
||||
.addElement(baseEl)
|
||||
@ -27,7 +27,7 @@ export const iosLeaveAnimation = (
|
||||
.addAnimation([backdropAnimation, wrapperAnimation]);
|
||||
|
||||
if (presentingEl) {
|
||||
const modalTransform = (presentingEl.tagName === 'ION-MODAL' && (presentingEl as HTMLIonModalElement).presentingElement !== undefined) ? 40 : 0;
|
||||
const modalTransform = (presentingEl.tagName === 'ION-MODAL' && (presentingEl as HTMLIonModalElement).presentingElement !== undefined) ? '-10px' : 'calc(var(--ion-safe-area-top) + 10px)';
|
||||
const bodyEl = document.body;
|
||||
const currentPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
||||
const presentingAnimation = createAnimation()
|
||||
@ -44,7 +44,7 @@ export const iosLeaveAnimation = (
|
||||
}
|
||||
})
|
||||
.keyframes([
|
||||
{ offset: 0, transform: `translateY(${-modalTransform}px) scale(${currentPresentingScale})`, 'border-radius': '10px 10px 0 0' },
|
||||
{ offset: 0, transform: `translateY(${modalTransform}) scale(${currentPresentingScale})`, 'border-radius': '10px 10px 0 0' },
|
||||
{ offset: 1, transform: 'translateY(0px) scale(1)', 'border-radius': '0px' }
|
||||
]);
|
||||
|
||||
|
@ -5,11 +5,7 @@ import { clamp } from '../../../utils/helpers';
|
||||
|
||||
// Defaults for the card swipe animation
|
||||
export const SwipeToCloseDefaults = {
|
||||
MIN_BACKDROP_OPACITY: 0.4,
|
||||
MIN_PRESENTING_SCALE: 0.95,
|
||||
MIN_Y_CARD: 44,
|
||||
MIN_Y_FULLSCREEN: 0,
|
||||
MIN_PRESENTING_Y: 0
|
||||
MIN_PRESENTING_SCALE: 0.93,
|
||||
};
|
||||
|
||||
export const createSwipeToCloseGesture = (
|
||||
@ -70,16 +66,20 @@ export const createSwipeToCloseGesture = (
|
||||
const duration = (shouldComplete) ? computeDuration(step * height, velocity) : computeDuration((1 - step) * height, velocity);
|
||||
isOpen = shouldComplete;
|
||||
|
||||
gesture.enable(false);
|
||||
|
||||
animation
|
||||
.onFinish(() => {
|
||||
if (shouldComplete) {
|
||||
onDismiss();
|
||||
} else {
|
||||
gesture.enable(true);
|
||||
}
|
||||
})
|
||||
.progressEnd((shouldComplete) ? 1 : 0, newStepValue, duration);
|
||||
};
|
||||
|
||||
return createGesture({
|
||||
const gesture = createGesture({
|
||||
el,
|
||||
gestureName: 'modalSwipeToClose',
|
||||
gesturePriority: 40,
|
||||
@ -90,8 +90,9 @@ export const createSwipeToCloseGesture = (
|
||||
onMove,
|
||||
onEnd
|
||||
});
|
||||
return gesture;
|
||||
};
|
||||
|
||||
const computeDuration = (remaining: number, velocity: number) => {
|
||||
return clamp(100, remaining / Math.abs(velocity * 1.1), 400);
|
||||
return clamp(400, remaining / Math.abs(velocity * 1.1), 500);
|
||||
};
|
||||
|
@ -20,10 +20,12 @@
|
||||
}
|
||||
|
||||
:host(.modal-card) {
|
||||
--backdrop-opacity: 0.15;
|
||||
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
:host(.modal-card) .modal-wrapper {
|
||||
@include border-radius($modal-ios-border-radius, $modal-ios-border-radius, 0, 0);
|
||||
height: calc(100% - 40px);
|
||||
height: calc(100% - var(--ion-safe-area-top) - 20px);
|
||||
}
|
@ -4,6 +4,8 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Modal - Spec</title>
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link href="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||
|
@ -30,6 +30,14 @@ body.backdrop-no-scroll {
|
||||
// --overflow: hidden;
|
||||
// }
|
||||
|
||||
// Modal - Card Style
|
||||
// --------------------------------------------------
|
||||
// The card style does not reach all the way to
|
||||
// the top of the screen, so there does not need
|
||||
// to be any safe area padding added
|
||||
ion-modal.modal-card .ion-page > ion-header > ion-toolbar:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
// Ionic Colors
|
||||
// --------------------------------------------------
|
||||
|
Reference in New Issue
Block a user