diff --git a/src/common/Hooks.res b/src/common/Hooks.res
index 5617bf2aa..e20fda83b 100644
--- a/src/common/Hooks.res
+++ b/src/common/Hooks.res
@@ -21,31 +21,48 @@ type scrollDir =
   | Up({scrollY: int})
   | Down({scrollY: int})
 
+type action =
+  | Skip
+  | EnterTop
+  | DownToUp
+  | UpToDown
+  | KeepDown
+  | KeepUp
+
 /**
   This will cause highly frequent events, so use it only once in a root as possible.
   And split the children components to prevent heavy ones from being re-rendered unnecessarily. */
-let useScrollDirection = () => {
-  let (_, startScrollEventTransition) = React.useTransition()
-  let (scrollDir, setScrollDir) = React.useState(() => Up({scrollY: %raw(`Infinity`)}))
+let useScrollDirection = (~topMargin=80, ~threshold=20) => {
+  let (scrollDir, setScrollDir) = React.useState(() => Up({
+    scrollY: 999999, // pseudo infinity
+  }))
 
   React.useEffect(() => {
     let onScroll = _e => {
-      startScrollEventTransition(() => {
-        setScrollDir(
-          prev => {
-            let Up({scrollY}) | Down({scrollY}) = prev
-            if scrollY === 0 || scrollY > Webapi.Window.scrollY {
-              Up({scrollY: Webapi.Window.scrollY})
-            } else {
-              Down({scrollY: Webapi.Window.scrollY})
-            }
-          },
-        )
+      setScrollDir(prev => {
+        let scrollY = Webapi.Window.scrollY
+        let enterTopMargin = scrollY <= topMargin
+
+        let action = switch prev {
+        | Up(_) if enterTopMargin => Skip
+        | Down(_) if enterTopMargin => EnterTop
+        | Up({scrollY: prevScrollY}) if prevScrollY < scrollY => UpToDown
+        | Up({scrollY: prevScrollY}) if prevScrollY - threshold >= scrollY => KeepUp
+        | Down({scrollY: prevScrollY}) if scrollY < prevScrollY => DownToUp
+        | Down({scrollY: prevScrollY}) if scrollY - threshold >= prevScrollY => KeepDown
+        | _ => Skip
+        }
+
+        switch action {
+        | Skip => prev
+        | EnterTop | DownToUp | KeepUp => Up({scrollY: scrollY})
+        | UpToDown | KeepDown => Down({scrollY: scrollY})
+        }
       })
     }
     Webapi.Window.addEventListener("scroll", onScroll)
     Some(() => Webapi.Window.removeEventListener("scroll", onScroll))
-  }, [])
+  }, [topMargin, threshold])
 
   scrollDir
 }