mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix(app): add a quick modal motion preset and settle instant modals (#1943)
This commit is contained in:
1 parent
2377a4c9d0
commit
9219b886fe
2 files changed
+123
-58
No files matched your search
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import styles from '@app/features/app/components/dialogs/Modal.module.css';
|
||||
import {resolveModalBackdropMotionSpec, resolveModalMotionSpec} from '@app/features/app/components/dialogs/ModalMotion';
|
||||
import {useModalBackHandler} from '@app/features/app/hooks/useModalBackHandler';
|
||||
import {CLOSE_DESCRIPTOR} from '@app/features/i18n/utils/CommonMessageDescriptors';
|
||||
import * as PopoutCommands from '@app/features/ui/commands/PopoutCommands';
|
||||
@@ -103,51 +104,16 @@ const RootComponent = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
},
|
||||
[ref],
|
||||
);
|
||||
const mobileFullscreenAnimations = {
|
||||
initial: {opacity: 0},
|
||||
animate: {opacity: 1},
|
||||
exit: {opacity: 0},
|
||||
};
|
||||
const profileSlideAnimations = prefersReducedMotion
|
||||
? {
|
||||
initial: {opacity: 0},
|
||||
animate: {opacity: 1},
|
||||
exit: {opacity: 0},
|
||||
}
|
||||
: {
|
||||
initial: {opacity: 0, x: 14},
|
||||
animate: {opacity: 1, x: 0},
|
||||
exit: {opacity: 0, x: 14},
|
||||
};
|
||||
const defaultAnimations = prefersReducedMotion
|
||||
? {
|
||||
initial: {opacity: 0},
|
||||
animate: {opacity: 1},
|
||||
exit: {opacity: 0},
|
||||
}
|
||||
: {
|
||||
initial: {opacity: 0, scale: 0.95},
|
||||
animate: {opacity: 1, scale: 1},
|
||||
exit: {opacity: 0, scale: 0.95},
|
||||
};
|
||||
const animations = isFullscreenOnMobile
|
||||
? mobileFullscreenAnimations
|
||||
: transitionPreset === 'profile-slide'
|
||||
? profileSlideAnimations
|
||||
: defaultAnimations;
|
||||
const rootTransition: Transition =
|
||||
prefersReducedMotion || transitionPreset === 'instant'
|
||||
? {duration: 0}
|
||||
: isFullscreenOnMobile
|
||||
? {duration: 0.15}
|
||||
: transitionPreset === 'profile-slide'
|
||||
? {duration: 0.14, ease: 'easeOut'}
|
||||
: {
|
||||
type: 'spring',
|
||||
stiffness: 400,
|
||||
damping: 30,
|
||||
mass: 0.8,
|
||||
};
|
||||
const motionSpec = resolveModalMotionSpec({
|
||||
transitionPreset,
|
||||
prefersReducedMotion,
|
||||
isFullscreenOnMobile,
|
||||
});
|
||||
const backdropMotionSpec = resolveModalBackdropMotionSpec({
|
||||
transitionPreset,
|
||||
prefersReducedMotion,
|
||||
isMobile,
|
||||
});
|
||||
const handleBackdropClickEvent = useCallback(
|
||||
(event: React.MouseEvent) => {
|
||||
if (event.target === event.currentTarget) {
|
||||
@@ -226,23 +192,16 @@ const RootComponent = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
};
|
||||
}, [isVisible]);
|
||||
const isCenteredOnMobile = isMobile && !useFullscreenLayer;
|
||||
const shouldInstantBackdrop = isMobile && !prefersReducedMotion;
|
||||
return (
|
||||
<FloatingPortal root={portalHost ?? undefined} data-flx="app.modal.floating-portal">
|
||||
{needsBackdrop && isVisible && (
|
||||
<motion.div
|
||||
className={styles.modalBackdrop}
|
||||
style={{zIndex: backdropZIndex}}
|
||||
initial={{opacity: shouldInstantBackdrop || isInstantTransition ? 0.85 : 0}}
|
||||
animate={{opacity: 0.85}}
|
||||
exit={{opacity: 0}}
|
||||
transition={
|
||||
prefersReducedMotion || isInstantTransition
|
||||
? {duration: 0}
|
||||
: shouldInstantBackdrop
|
||||
? {duration: 0.15}
|
||||
: {duration: 0.2}
|
||||
}
|
||||
initial={backdropMotionSpec.initial}
|
||||
animate={backdropMotionSpec.animate}
|
||||
exit={backdropMotionSpec.exit}
|
||||
transition={backdropMotionSpec.transition as Transition}
|
||||
data-flx="app.modal.modal-backdrop"
|
||||
/>
|
||||
)}
|
||||
@@ -326,8 +285,10 @@ const RootComponent = React.forwardRef<HTMLDivElement, ModalProps>(
|
||||
className,
|
||||
)}
|
||||
data-flx="app.modal.root"
|
||||
{...animations}
|
||||
transition={rootTransition}
|
||||
initial={motionSpec.initial}
|
||||
animate={motionSpec.animate}
|
||||
exit={motionSpec.exit}
|
||||
transition={motionSpec.transition as Transition}
|
||||
onAnimationStart={handleAnimationStart}
|
||||
onAnimationComplete={handleAnimationComplete}
|
||||
ref={setMotionElementRef}
|
||||
|
||||
Reference in new issue
Block a user