Smart Header: Disappears when scrolling

PreviousNext
Docs
react-marketcomponent

Preview

Loading preview…
use-smart-header.tsx
import { useMotionValue, useSpring } from "motion/react";
import { useEffect, useRef } from "react";

export function useSmartHeader(headerPx = 64, snapDelay = 120) {
  const yRaw = useMotionValue(0); // 0 = fully shown
  const y = useSpring(yRaw, { stiffness: 400, damping: 40 });

  const lastY = useRef(0);
  const snapTimer = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    const onScroll = () => {
      const cur = window.scrollY;

      /* Always show at top, even if the user scrolled up slowly to the top */
      if (cur <= 50) {
        yRaw.set(0); // fully visible
        lastY.current = 0;
        return;
      }

      const delta = cur - lastY.current;
      lastY.current = cur;

      // move header opposite to scroll direction, clamped
      const next = Math.max(Math.min(yRaw.get() - delta, 0), -headerPx);
      yRaw.set(next);

      if (snapTimer.current !== null) {
        clearTimeout(snapTimer.current);
      }
      snapTimer.current = setTimeout(() => {
        const pos = yRaw.get();
        yRaw.set(pos < -headerPx / 2 ? -headerPx : 0); // snap
      }, snapDelay);
    };

    window.addEventListener("scroll", onScroll, { passive: true });
    return () => window.removeEventListener("scroll", onScroll);
  }, [headerPx, snapDelay, yRaw]);

  return y; // spring-smoothed motion value
}

Installation

npx shadcn@latest add @react-market/smart-header

Usage

import { SmartHeader } from "@/components/smart-header"
<SmartHeader />