mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 18:54:11 +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]);
|
.addAnimation([backdropAnimation, wrapperAnimation]);
|
||||||
|
|
||||||
if (presentingEl) {
|
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 bodyEl = document.body;
|
||||||
const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
const toPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
||||||
const finalTransform = `translateY(${-modalTransform}px) scale(${toPresentingScale})`;
|
const finalTransform = `translateY(${modalTransform}) scale(${toPresentingScale})`;
|
||||||
|
|
||||||
const presentingAnimation = createAnimation()
|
const presentingAnimation = createAnimation()
|
||||||
.beforeStyles({
|
.beforeStyles({
|
||||||
'transform': 'translateY(0)'
|
'transform': 'translateY(0)',
|
||||||
|
'transform-origin': 'top center'
|
||||||
})
|
})
|
||||||
.afterStyles({
|
.afterStyles({
|
||||||
'transform': finalTransform
|
'transform': finalTransform
|
||||||
|
@ -18,7 +18,7 @@ export const iosLeaveAnimation = (
|
|||||||
const wrapperAnimation = createAnimation()
|
const wrapperAnimation = createAnimation()
|
||||||
.addElement(baseEl.querySelector('.modal-wrapper')!)
|
.addElement(baseEl.querySelector('.modal-wrapper')!)
|
||||||
.beforeStyles({ 'opacity': 1 })
|
.beforeStyles({ 'opacity': 1 })
|
||||||
.fromTo('transform', `translateY(0%)`, 'translateY(100%)');
|
.fromTo('transform', 'translateY(0%)', 'translateY(100%)');
|
||||||
|
|
||||||
const baseAnimation = createAnimation()
|
const baseAnimation = createAnimation()
|
||||||
.addElement(baseEl)
|
.addElement(baseEl)
|
||||||
@ -27,7 +27,7 @@ export const iosLeaveAnimation = (
|
|||||||
.addAnimation([backdropAnimation, wrapperAnimation]);
|
.addAnimation([backdropAnimation, wrapperAnimation]);
|
||||||
|
|
||||||
if (presentingEl) {
|
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 bodyEl = document.body;
|
||||||
const currentPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
const currentPresentingScale = SwipeToCloseDefaults.MIN_PRESENTING_SCALE;
|
||||||
const presentingAnimation = createAnimation()
|
const presentingAnimation = createAnimation()
|
||||||
@ -44,7 +44,7 @@ export const iosLeaveAnimation = (
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.keyframes([
|
.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' }
|
{ 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
|
// Defaults for the card swipe animation
|
||||||
export const SwipeToCloseDefaults = {
|
export const SwipeToCloseDefaults = {
|
||||||
MIN_BACKDROP_OPACITY: 0.4,
|
MIN_PRESENTING_SCALE: 0.93,
|
||||||
MIN_PRESENTING_SCALE: 0.95,
|
|
||||||
MIN_Y_CARD: 44,
|
|
||||||
MIN_Y_FULLSCREEN: 0,
|
|
||||||
MIN_PRESENTING_Y: 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createSwipeToCloseGesture = (
|
export const createSwipeToCloseGesture = (
|
||||||
@ -70,16 +66,20 @@ export const createSwipeToCloseGesture = (
|
|||||||
const duration = (shouldComplete) ? computeDuration(step * height, velocity) : computeDuration((1 - step) * height, velocity);
|
const duration = (shouldComplete) ? computeDuration(step * height, velocity) : computeDuration((1 - step) * height, velocity);
|
||||||
isOpen = shouldComplete;
|
isOpen = shouldComplete;
|
||||||
|
|
||||||
|
gesture.enable(false);
|
||||||
|
|
||||||
animation
|
animation
|
||||||
.onFinish(() => {
|
.onFinish(() => {
|
||||||
if (shouldComplete) {
|
if (shouldComplete) {
|
||||||
onDismiss();
|
onDismiss();
|
||||||
|
} else {
|
||||||
|
gesture.enable(true);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.progressEnd((shouldComplete) ? 1 : 0, newStepValue, duration);
|
.progressEnd((shouldComplete) ? 1 : 0, newStepValue, duration);
|
||||||
};
|
};
|
||||||
|
|
||||||
return createGesture({
|
const gesture = createGesture({
|
||||||
el,
|
el,
|
||||||
gestureName: 'modalSwipeToClose',
|
gestureName: 'modalSwipeToClose',
|
||||||
gesturePriority: 40,
|
gesturePriority: 40,
|
||||||
@ -90,8 +90,9 @@ export const createSwipeToCloseGesture = (
|
|||||||
onMove,
|
onMove,
|
||||||
onEnd
|
onEnd
|
||||||
});
|
});
|
||||||
|
return gesture;
|
||||||
};
|
};
|
||||||
|
|
||||||
const computeDuration = (remaining: number, velocity: number) => {
|
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) {
|
:host(.modal-card) {
|
||||||
|
--backdrop-opacity: 0.15;
|
||||||
|
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host(.modal-card) .modal-wrapper {
|
:host(.modal-card) .modal-wrapper {
|
||||||
@include border-radius($modal-ios-border-radius, $modal-ios-border-radius, 0, 0);
|
@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>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>Modal - Spec</title>
|
<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">
|
<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="../../../../../css/ionic.bundle.css" rel="stylesheet">
|
||||||
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet">
|
||||||
|
@ -30,6 +30,14 @@ body.backdrop-no-scroll {
|
|||||||
// --overflow: hidden;
|
// --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
|
// Ionic Colors
|
||||||
// --------------------------------------------------
|
// --------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user