FIX: mobile modal tweaks (#27073)

- removes `will-change: auto;` which is a performance hack which should be avoided and is probably causing more harm than good here
- lowers swipe velocity to 0.4 to ensure the modal can be dismissed with the thumb
- uses JS CSS animate API to animate the backdrop opacity
- uses the height of the modal container to have more precise values when computing backdrop opacity
- animate the modal container instead of the wrapper
- removes a useless template-lint-disable directive
- simplify the closing animation
- various small code tweaks to limit indirection
This commit is contained in:
Joffrey JAFFEUX 2024-05-19 15:43:03 +02:00 committed by GitHub
parent 875a413164
commit f752851030
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 37 deletions

View File

@ -29,7 +29,7 @@ export const CLOSE_INITIATED_BY_SWIPE_DOWN = "initiatedBySwipeDown";
const FLASH_TYPES = ["success", "error", "warning", "info"];
const SWIPE_VELOCITY_THRESHOLD = 0.7;
const SWIPE_VELOCITY_THRESHOLD = 0.4;
export default class DModal extends Component {
@service modal;
@ -39,15 +39,19 @@ export default class DModal extends Component {
@tracked wrapperElement;
@tracked animating = false;
registerModalContainer = modifierFn((element) => {
this.modalContainer = element;
});
setupModalBody = modifierFn((element) => {
if (this.site.mobileView) {
disableBodyScroll(element);
if (!this.site.mobileView) {
return;
}
disableBodyScroll(element);
return () => {
if (this.site.mobileView) {
enableBodyScroll(element);
}
enableBodyScroll(element);
};
});
@ -139,19 +143,15 @@ export default class DModal extends Component {
return;
}
if (swipeEvent.goingUp()) {
if (
swipeEvent.goingUp() ||
swipeEvent.velocityY < SWIPE_VELOCITY_THRESHOLD
) {
return await this.#animateWrapperPosition(0);
}
if (swipeEvent.velocityY >= SWIPE_VELOCITY_THRESHOLD) {
this.wrapperElement.querySelector(
".d-modal__container"
).style.transform = `translateY(${swipeEvent.deltaY}px)`;
this.closeModal(CLOSE_INITIATED_BY_SWIPE_DOWN);
} else {
return await this.#animateWrapperPosition(0);
}
this.modalContainer.style.transform = `translateY(${swipeEvent.deltaY}px)`;
this.closeModal(CLOSE_INITIATED_BY_SWIPE_DOWN);
}
@action
@ -178,15 +178,8 @@ export default class DModal extends Component {
this.#animateBackdropOpacity(window.innerHeight);
await this.wrapperElement.animate(
[
// hidding first ms to avoid flicker
{ visibility: "hidden", offset: 0 },
{ visibility: "visible", offset: 0.01 },
{ transform: "translateY(100%)", offset: 1 },
],
{ duration: getMaxAnimationTimeMs(), fill: "forwards" }
).finished;
await this.#animateWrapperPosition(this.modalContainer.clientHeight);
this.animating = false;
}
@ -252,21 +245,16 @@ export default class DModal extends Component {
return;
}
// 85vh is the max height of the modal
const opacity = 1 - position / (window.innerHeight * 0.85);
requestAnimationFrame(() => {
backdrop.style.setProperty(
"opacity",
Math.max(0, Math.min(opacity, 0.6)),
"important"
);
const opacity = 1 - position / this.modalContainer.clientHeight;
backdrop.animate([{ opacity: Math.max(0, Math.min(opacity, 0.6)) }], {
fill: "forwards",
});
}
async #animateWrapperPosition(position) {
this.#animateBackdropOpacity(position);
await this.wrapperElement.animate(
await this.modalContainer.animate(
[{ transform: `translateY(${position}px)` }],
{
fill: "forwards",
@ -276,7 +264,6 @@ export default class DModal extends Component {
}
<template>
{{! template-lint-disable no-pointer-down-event-binding }}
{{! template-lint-disable no-invalid-interactive }}
<ConditionalInElement
@ -300,7 +287,7 @@ export default class DModal extends Component {
{{willDestroy this.cleanupModal}}
{{trapTab preventScroll=false}}
>
<div class="d-modal__container">
<div class="d-modal__container" {{this.registerModalContainer}}>
{{yield to="aboveHeader"}}
{{#if

View File

@ -34,7 +34,6 @@ html:not(.keyboard-visible.mobile-view) {
width: 100%;
max-width: 100%;
max-height: calc(var(--composer-vh, var(--1dvh)) * 85);
will-change: auto;
}
&__header {