Skip to content

Commit

Permalink
fix(modal): account for safe area on devices with a notch (#20072)
Browse files Browse the repository at this point in the history
* fix card modal on notch phones

* only apply safe area for card modal

* fix styles, fix gesture race condition

* a few more tweaks
  • Loading branch information
liamdebeasi committed Dec 16, 2019
1 parent 9d1fe2e commit 1cabb53
Show file tree
Hide file tree
Showing 6 changed files with 28 additions and 14 deletions.
7 changes: 4 additions & 3 deletions core/src/components/modal/animations/ios.enter.ts
Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions core/src/components/modal/animations/ios.leave.ts
Expand Up @@ -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)
Expand All @@ -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()
Expand All @@ -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' }
]);

Expand Down
15 changes: 8 additions & 7 deletions core/src/components/modal/gestures/swipe-to-close.ts
Expand Up @@ -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 = (
Expand Down Expand Up @@ -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,
Expand All @@ -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);
};
4 changes: 3 additions & 1 deletion core/src/components/modal/modal.ios.scss
Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions core/src/components/modal/test/spec/index.html
Expand Up @@ -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">
Expand Down
8 changes: 8 additions & 0 deletions core/src/css/core.scss
Expand Up @@ -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
// --------------------------------------------------
Expand Down

0 comments on commit 1cabb53

Please sign in to comment.