mirror of
https://github.com/discourse/discourse.git
synced 2025-02-18 00:22:46 +08:00
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:
parent
875a413164
commit
f752851030
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in New Issue
Block a user