Fix scroll bounce bug

pull/114/head
J M Rossy 2 months ago
parent 0bace4598d
commit b78b86a414
  1. 16
      src/components/nav/Header.tsx
  2. 38
      src/utils/useScrollListener.ts

@ -1,6 +1,6 @@
import Image from 'next/image';
import Link from 'next/link';
import { PropsWithChildren, useEffect, useState } from 'react';
import { PropsWithChildren } from 'react';
import { DropdownMenu } from '@hyperlane-xyz/widgets';
@ -9,6 +9,7 @@ import Explorer from '../../images/logos/hyperlane-explorer.svg';
import Logo from '../../images/logos/hyperlane-logo.svg';
import Name from '../../images/logos/hyperlane-name.svg';
import { Color } from '../../styles/Color';
import { useScrollThresholdListener } from '../../utils/useScrollListener';
import { HyperlaneWideChevron } from '../icons/Chevron';
import { MiniSearchBar } from '../search/MiniSearchBar';
@ -16,18 +17,7 @@ const PAGES_EXCLUDING_SEARCH = ['/', '/debugger'];
export function Header({ pathName }: { pathName: string }) {
// For dynamic sizing on scroll
const [animateHeader, setAnimateHeader] = useState(false);
useEffect(() => {
const listener = () => {
if (window.scrollY > 100) {
setAnimateHeader(true);
} else setAnimateHeader(false);
};
window.addEventListener('scroll', listener);
return () => {
window.removeEventListener('scroll', listener);
};
}, []);
const animateHeader = useScrollThresholdListener(100);
const showSearch = !PAGES_EXCLUDING_SEARCH.includes(pathName);

@ -0,0 +1,38 @@
import { useEffect, useState } from 'react';
export function useScrollThresholdListener(threshold: number, debounce = 500) {
const [isAboveThreshold, setIsAbove] = useState(false);
const [isDebouncing, setIsDebouncing] = useState(false);
useEffect(() => {
let timeoutId: NodeJS.Timeout | null;
const listener = () => {
if (isDebouncing) {
if (!timeoutId) {
setTimeout(() => {
setIsDebouncing(false);
timeoutId = null;
}, debounce);
}
return;
}
if (window.scrollY > threshold && !isAboveThreshold) {
setIsAbove(true);
setIsDebouncing(true);
} else if (window.scrollY <= threshold && isAboveThreshold) {
setIsAbove(false);
setIsDebouncing(true);
}
};
window.addEventListener('scroll', listener, { passive: true });
return () => {
window.removeEventListener('scroll', listener);
if (timeoutId) clearTimeout(timeoutId);
};
}, [threshold, debounce, isAboveThreshold, isDebouncing]);
return isAboveThreshold;
}
Loading…
Cancel
Save