hide/show header on delayed mobile scroll, prevent body scroll when sidebar shown
This commit is contained in:
parent
b3a697caed
commit
42b02fe5bb
@ -52,8 +52,11 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
const [userDropdownOpen, setUserDropdownOpen] = useState(false);
|
const [userDropdownOpen, setUserDropdownOpen] = useState(false);
|
||||||
const [menuTranslate, setMenuTranslate] = useState<number | null>(null);
|
const [menuTranslate, setMenuTranslate] = useState<number | null>(null);
|
||||||
const [notificationsTranslate, setNotificationsTranslate] = useState<number | null>(null);
|
const [notificationsTranslate, setNotificationsTranslate] = useState<number | null>(null);
|
||||||
|
const [navbarShowing, setNavbarShowing] = useState(true);
|
||||||
const reloaded = useReloaded();
|
const reloaded = useReloaded();
|
||||||
const menusOpened = useRef(false);
|
const menusOpened = useRef(false);
|
||||||
|
const scrollOffset = useRef(0);
|
||||||
|
const lastScroll = useRef<number | null>(null);
|
||||||
|
|
||||||
const path = pathname === '/' ? (user?.homepage ?? '/dashboard') : pathname;
|
const path = pathname === '/' ? (user?.homepage ?? '/dashboard') : pathname;
|
||||||
|
|
||||||
@ -71,8 +74,23 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
router.replace('', { scroll: false });
|
router.replace('', { scroll: false });
|
||||||
}, [router, reloaded]);
|
}, [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({
|
const { ref } = useSwipeable({
|
||||||
touchEventOptions: { passive: false },
|
touchEventOptions: { passive: true },
|
||||||
onSwiped: e => {
|
onSwiped: e => {
|
||||||
const speedX = Math.abs(e.vxvy[0]);
|
const speedX = Math.abs(e.vxvy[0]);
|
||||||
const speedY = Math.abs(e.vxvy[1]);
|
const speedY = Math.abs(e.vxvy[1]);
|
||||||
@ -90,6 +108,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
|
|
||||||
setMenuTranslate(null);
|
setMenuTranslate(null);
|
||||||
setNotificationsTranslate(null);
|
setNotificationsTranslate(null);
|
||||||
|
if (!isMenuOpen && !isNotificationsOpen)
|
||||||
document.body.classList.remove('touch-none', 'overflow-hidden');
|
document.body.classList.remove('touch-none', 'overflow-hidden');
|
||||||
},
|
},
|
||||||
onSwipeStart: e => {
|
onSwipeStart: e => {
|
||||||
@ -109,21 +128,17 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
|
|
||||||
if ((isMenuOpen && e.dir === 'Left') || (allMenusClosed && e.dir === 'Right' && xPercent <= 0.6)) {
|
if ((isMenuOpen && e.dir === 'Left') || (allMenusClosed && e.dir === 'Right' && xPercent <= 0.6)) {
|
||||||
setMenuTranslate(e.deltaX);
|
setMenuTranslate(e.deltaX);
|
||||||
e.event.preventDefault();
|
|
||||||
document.body.classList.add('touch-none', 'overflow-hidden');
|
document.body.classList.add('touch-none', 'overflow-hidden');
|
||||||
} else if ((isNotificationsOpen && e.dir === 'Right' || (allMenusClosed && e.dir === 'Left' && xPercent >= 0.4))) {
|
} else if ((isNotificationsOpen && e.dir === 'Right' || (allMenusClosed && e.dir === 'Left' && xPercent >= 0.4))) {
|
||||||
setNotificationsTranslate(e.deltaX);
|
setNotificationsTranslate(e.deltaX);
|
||||||
e.event.preventDefault();
|
|
||||||
document.body.classList.add('touch-none', 'overflow-hidden');
|
document.body.classList.add('touch-none', 'overflow-hidden');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSwiping: e => {
|
onSwiping: e => {
|
||||||
if (menuTranslate !== null) {
|
if (menuTranslate !== null) {
|
||||||
setMenuTranslate(e.deltaX);
|
setMenuTranslate(e.deltaX);
|
||||||
e.event.preventDefault();
|
|
||||||
} else if (notificationsTranslate !== null) {
|
} else if (notificationsTranslate !== null) {
|
||||||
setNotificationsTranslate(e.deltaX);
|
setNotificationsTranslate(e.deltaX);
|
||||||
e.event.preventDefault();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}) as { ref: RefCallback<Document>; };
|
}) as { ref: RefCallback<Document>; };
|
||||||
@ -133,6 +148,13 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
return () => ref({} as any);
|
return () => ref({} as any);
|
||||||
}, [ref]);
|
}, [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(() => {
|
useEffect(() => {
|
||||||
if (user)
|
if (user)
|
||||||
getFriendRequests().then(setFriendRequests);
|
getFriendRequests().then(setFriendRequests);
|
||||||
@ -236,7 +258,8 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
}, [friendRequests]);
|
}, [friendRequests]);
|
||||||
|
|
||||||
const topNavbar = useMemo(() => {
|
const topNavbar = useMemo(() => {
|
||||||
return (<Navbar className="w-full fixed" classNames={{ wrapper: 'max-w-full p-0' }} shouldHideOnScroll={breakpoint === undefined} height="5.5rem">
|
return (<Navbar className={`w-lvw fixed transition ${!navbarShowing && breakpoint === undefined ? '-translate-y-full' : ''}`}
|
||||||
|
classNames={{ wrapper: 'max-w-full p-0' }} height="5.5rem">
|
||||||
<div className="flex h-header px-6 items-center flex-shrink-0 w-full z-[48]">
|
<div className="flex h-header px-6 items-center flex-shrink-0 w-full z-[48]">
|
||||||
<Button className="text-2xl font-bold cursor-pointer flex items-center m-0 ps-1.5 pe-2 mr-6" variant="light"
|
<Button className="text-2xl font-bold cursor-pointer flex items-center m-0 ps-1.5 pe-2 mr-6" variant="light"
|
||||||
onClick={() => setMenuOpen(true)}>
|
onClick={() => setMenuOpen(true)}>
|
||||||
@ -323,7 +346,7 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</Navbar>);
|
</Navbar>);
|
||||||
}, [breakpoint, routeGroup, friendRequests, userDropdownOpen, isNotificationsOpen, user, notifications]);
|
}, [breakpoint, routeGroup, friendRequests, userDropdownOpen, isNotificationsOpen, user, notifications, navbarShowing]);
|
||||||
|
|
||||||
const leftSidebar = useMemo(() => {
|
const leftSidebar = useMemo(() => {
|
||||||
return (<div className={`fixed inset-0 w-full h-full z-[49] ${isMenuOpen ? '' : 'pointer-events-none'}`}>
|
return (<div className={`fixed inset-0 w-full h-full z-[49] ${isMenuOpen ? '' : 'pointer-events-none'}`}>
|
||||||
@ -472,10 +495,10 @@ export const HeaderSidebar = ({ children }: HeaderSidebarProps) => {
|
|||||||
{ leftSidebar }
|
{ leftSidebar }
|
||||||
{ rightSidebar }
|
{ rightSidebar }
|
||||||
{/* begin top navbar */}
|
{/* begin top navbar */}
|
||||||
<div className="flex flex-col flex-grow">
|
<div className="flex flex-col flex-grow h-full">
|
||||||
{topNavbar}
|
{topNavbar}
|
||||||
|
|
||||||
<div className={`sm:px-5 flex-grow pt-fixed flex flex-col`}>
|
<div className={`sm:px-5 flex-grow pt-fixed flex flex-col h-full`}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -16,6 +16,10 @@ $scrollbar-size: 13px;
|
|||||||
|
|
||||||
// dont theme scrollbars on mobile
|
// dont theme scrollbars on mobile
|
||||||
@media (hover: hover) {
|
@media (hover: hover) {
|
||||||
|
html {
|
||||||
|
scrollbar-gutter: stable;
|
||||||
|
}
|
||||||
|
|
||||||
@supports not selector(::-webkit-scrollbar) {
|
@supports not selector(::-webkit-scrollbar) {
|
||||||
* {
|
* {
|
||||||
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg);
|
scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg);
|
||||||
|
@ -492,7 +492,6 @@ const payloadValid = (payload: any, filterers: Filterers<any, any>) => {
|
|||||||
for (const filterer of filterers) {
|
for (const filterer of filterers) {
|
||||||
if (!(filterer.name in payload)) continue;
|
if (!(filterer.name in payload)) continue;
|
||||||
const data = payload[filterer.name];
|
const data = payload[filterer.name];
|
||||||
console.log(filterer.name, data)
|
|
||||||
if (filterer.type === 'select' && !(data instanceof Set))
|
if (filterer.type === 'select' && !(data instanceof Set))
|
||||||
return false;
|
return false;
|
||||||
if (filterer.type === 'slider' && !Array.isArray(data))
|
if (filterer.type === 'slider' && !Array.isArray(data))
|
||||||
|
Loading…
Reference in New Issue
Block a user