From 92b1d30cbbf2372ba3d4d8589214068a5b5ab02a Mon Sep 17 00:00:00 2001 From: PEDZEO Date: Tue, 20 Jan 2026 03:52:27 +0300 Subject: [PATCH] Refactor scroll locking in ConnectionModal and TopUpModal: simplify the implementation by removing unnecessary style manipulations and enhancing event listeners for touch and wheel scroll prevention, ensuring a smoother user experience across devices. --- src/components/ConnectionModal.tsx | 48 ++++++++---------------------- src/components/TopUpModal.tsx | 47 ++++++++--------------------- src/components/layout/Layout.tsx | 17 +++++++---- 3 files changed, 38 insertions(+), 74 deletions(-) diff --git a/src/components/ConnectionModal.tsx b/src/components/ConnectionModal.tsx index f2c28e4..f47e64d 100644 --- a/src/components/ConnectionModal.tsx +++ b/src/components/ConnectionModal.tsx @@ -237,53 +237,31 @@ export default function ConnectionModal({ onClose }: ConnectionModalProps) { modalContentRef.current?.scrollTo({ top: 0, behavior: 'instant' }) }, [showAppSelector]) - // Scroll lock when modal is open (cross-platform including Android) + // Scroll lock when modal is open useEffect(() => { const scrollY = window.scrollY - const body = document.body - const html = document.documentElement - // Save original styles - const originalStyles = { - bodyOverflow: body.style.overflow, - bodyPosition: body.style.position, - bodyTop: body.style.top, - bodyWidth: body.style.width, - bodyHeight: body.style.height, - htmlOverflow: html.style.overflow, - htmlHeight: html.style.height, - bodyTouchAction: body.style.touchAction, - } - - // Lock scroll - body.style.overflow = 'hidden' - body.style.position = 'fixed' - body.style.top = `-${scrollY}px` - body.style.width = '100%' - body.style.height = '100%' - body.style.touchAction = 'none' - html.style.overflow = 'hidden' - html.style.height = '100%' - - // Prevent touchmove on backdrop (Android fix) + // Prevent all touch/wheel scroll on backdrop const preventScroll = (e: TouchEvent) => { const target = e.target as HTMLElement - // Allow scroll inside modal content if (target.closest('[data-modal-content]')) return e.preventDefault() } + + const preventWheel = (e: WheelEvent) => { + const target = e.target as HTMLElement + if (target.closest('[data-modal-content]')) return + e.preventDefault() + } + document.addEventListener('touchmove', preventScroll, { passive: false }) + document.addEventListener('wheel', preventWheel, { passive: false }) + document.body.style.overflow = 'hidden' return () => { - body.style.overflow = originalStyles.bodyOverflow - body.style.position = originalStyles.bodyPosition - body.style.top = originalStyles.bodyTop - body.style.width = originalStyles.bodyWidth - body.style.height = originalStyles.bodyHeight - body.style.touchAction = originalStyles.bodyTouchAction - html.style.overflow = originalStyles.htmlOverflow - html.style.height = originalStyles.htmlHeight document.removeEventListener('touchmove', preventScroll) + document.removeEventListener('wheel', preventWheel) + document.body.style.overflow = '' window.scrollTo(0, scrollY) } }, []) diff --git a/src/components/TopUpModal.tsx b/src/components/TopUpModal.tsx index f9c3c5a..d419365 100644 --- a/src/components/TopUpModal.tsx +++ b/src/components/TopUpModal.tsx @@ -55,52 +55,31 @@ export default function TopUpModal({ method, onClose, initialAmountRubles }: Top ) const popupRef = useRef(null) - // Scroll lock when modal is open (cross-platform including Android) + // Scroll lock when modal is open useEffect(() => { const scrollY = window.scrollY - const body = document.body - const html = document.documentElement - // Save original styles - const originalStyles = { - bodyOverflow: body.style.overflow, - bodyPosition: body.style.position, - bodyTop: body.style.top, - bodyWidth: body.style.width, - bodyHeight: body.style.height, - htmlOverflow: html.style.overflow, - htmlHeight: html.style.height, - bodyTouchAction: body.style.touchAction, - } - - // Lock scroll - body.style.overflow = 'hidden' - body.style.position = 'fixed' - body.style.top = `-${scrollY}px` - body.style.width = '100%' - body.style.height = '100%' - body.style.touchAction = 'none' - html.style.overflow = 'hidden' - html.style.height = '100%' - - // Prevent touchmove on backdrop (Android fix) + // Prevent all touch/wheel scroll on backdrop const preventScroll = (e: TouchEvent) => { const target = e.target as HTMLElement if (target.closest('[data-modal-content]')) return e.preventDefault() } + + const preventWheel = (e: WheelEvent) => { + const target = e.target as HTMLElement + if (target.closest('[data-modal-content]')) return + e.preventDefault() + } + document.addEventListener('touchmove', preventScroll, { passive: false }) + document.addEventListener('wheel', preventWheel, { passive: false }) + document.body.style.overflow = 'hidden' return () => { - body.style.overflow = originalStyles.bodyOverflow - body.style.position = originalStyles.bodyPosition - body.style.top = originalStyles.bodyTop - body.style.width = originalStyles.bodyWidth - body.style.height = originalStyles.bodyHeight - body.style.touchAction = originalStyles.bodyTouchAction - html.style.overflow = originalStyles.htmlOverflow - html.style.height = originalStyles.htmlHeight document.removeEventListener('touchmove', preventScroll) + document.removeEventListener('wheel', preventWheel) + document.body.style.overflow = '' window.scrollTo(0, scrollY) } }, []) diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index 8bde09b..a682c1b 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -370,7 +370,7 @@ export default function Layout({ children }: LayoutProps) {
{/* Logo */} - + setMobileMenuOpen(false)} className={`flex items-center gap-2.5 flex-shrink-0 ${!appName ? 'lg:mr-4' : ''}`}>
{/* Always show letter as fallback */} @@ -435,7 +435,10 @@ export default function Layout({ children }: LayoutProps) { {/* Theme toggle button - only show if both themes are enabled */} {canToggle && ( )} - - +
setMobileMenuOpen(false)}> + +
+
setMobileMenuOpen(false)}> + +
{/* Hide language switcher on mobile when promo is active */} -
+
setMobileMenuOpen(false)}>