From 42b02fe5bbb08ab8d4a96c67ac0f68843d09ccce Mon Sep 17 00:00:00 2001 From: sk1982 Date: Fri, 12 Apr 2024 20:52:47 -0400 Subject: [PATCH] hide/show header on delayed mobile scroll, prevent body scroll when sidebar shown --- src/app/(with-header)/header-sidebar.tsx | 41 ++++++++++++++++++------ src/app/scrollbar.scss | 4 +++ src/components/filter-sorter.tsx | 1 - 3 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/app/(with-header)/header-sidebar.tsx b/src/app/(with-header)/header-sidebar.tsx index d9e17cb..271fd03 100644 --- a/src/app/(with-header)/header-sidebar.tsx +++ b/src/app/(with-header)/header-sidebar.tsx @@ -52,8 +52,11 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { const [userDropdownOpen, setUserDropdownOpen] = useState(false); const [menuTranslate, setMenuTranslate] = useState(null); const [notificationsTranslate, setNotificationsTranslate] = useState(null); + const [navbarShowing, setNavbarShowing] = useState(true); const reloaded = useReloaded(); const menusOpened = useRef(false); + const scrollOffset = useRef(0); + const lastScroll = useRef(null); const path = pathname === '/' ? (user?.homepage ?? '/dashboard') : pathname; @@ -71,8 +74,23 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { router.replace('', { scroll: false }); }, [router, reloaded]); + useWindowListener('scroll', () => { + if (lastScroll.current === null) lastScroll.current = window.scrollY; + scrollOffset.current += window.scrollY - lastScroll.current; + lastScroll.current = window.scrollY; + + if (scrollOffset.current < -100 || window.scrollY < 35) + setNavbarShowing(true); + else if (scrollOffset.current > 100) + setNavbarShowing(false); + }); + + useWindowListener('scrollend', () => { + scrollOffset.current = 0; + }); + const { ref } = useSwipeable({ - touchEventOptions: { passive: false }, + touchEventOptions: { passive: true }, onSwiped: e => { const speedX = Math.abs(e.vxvy[0]); const speedY = Math.abs(e.vxvy[1]); @@ -90,6 +108,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { setMenuTranslate(null); setNotificationsTranslate(null); + if (!isMenuOpen && !isNotificationsOpen) document.body.classList.remove('touch-none', 'overflow-hidden'); }, onSwipeStart: e => { @@ -109,21 +128,17 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { if ((isMenuOpen && e.dir === 'Left') || (allMenusClosed && e.dir === 'Right' && xPercent <= 0.6)) { setMenuTranslate(e.deltaX); - e.event.preventDefault(); document.body.classList.add('touch-none', 'overflow-hidden'); } else if ((isNotificationsOpen && e.dir === 'Right' || (allMenusClosed && e.dir === 'Left' && xPercent >= 0.4))) { setNotificationsTranslate(e.deltaX); - e.event.preventDefault(); document.body.classList.add('touch-none', 'overflow-hidden'); } }, onSwiping: e => { if (menuTranslate !== null) { setMenuTranslate(e.deltaX); - e.event.preventDefault(); } else if (notificationsTranslate !== null) { setNotificationsTranslate(e.deltaX); - e.event.preventDefault(); } } }) as { ref: RefCallback; }; @@ -133,6 +148,13 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { return () => ref({} as any); }, [ref]); + useEffect(() => { + if (isMenuOpen || isNotificationsOpen) + document.body.classList.add('touch-none', 'overflow-hidden'); + else + document.body.classList.remove('touch-none', 'overflow-hidden'); + }, [isMenuOpen, isNotificationsOpen]) + useEffect(() => { if (user) getFriendRequests().then(setFriendRequests); @@ -236,7 +258,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { }, [friendRequests]); const topNavbar = useMemo(() => { - return ( + return (
); - }, [breakpoint, routeGroup, friendRequests, userDropdownOpen, isNotificationsOpen, user, notifications]); + }, [breakpoint, routeGroup, friendRequests, userDropdownOpen, isNotificationsOpen, user, notifications, navbarShowing]); const leftSidebar = useMemo(() => { return (
@@ -472,10 +495,10 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => { { leftSidebar } { rightSidebar } {/* begin top navbar */} -
+
{topNavbar} -
+
{children}
diff --git a/src/app/scrollbar.scss b/src/app/scrollbar.scss index 889b26f..779fd89 100644 --- a/src/app/scrollbar.scss +++ b/src/app/scrollbar.scss @@ -16,6 +16,10 @@ $scrollbar-size: 13px; // dont theme scrollbars on mobile @media (hover: hover) { + html { + scrollbar-gutter: stable; + } + @supports not selector(::-webkit-scrollbar) { * { scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg); diff --git a/src/components/filter-sorter.tsx b/src/components/filter-sorter.tsx index dfdd47d..f948a27 100644 --- a/src/components/filter-sorter.tsx +++ b/src/components/filter-sorter.tsx @@ -492,7 +492,6 @@ const payloadValid = (payload: any, filterers: Filterers) => { for (const filterer of filterers) { if (!(filterer.name in payload)) continue; const data = payload[filterer.name]; - console.log(filterer.name, data) if (filterer.type === 'select' && !(data instanceof Set)) return false; if (filterer.type === 'slider' && !Array.isArray(data))