Docs
Reveal

Reveal

Scroll to reveal the navbar or hover to reveal the navbar content

Loading...

Installation

Create your utils file

Create utils.ts file

Create utils.ts file in the libs folder and paste the following code:

import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
 
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs));
}

Run the following command

It will create a new file reveal.tsx inside the components/navbars/reveal.tsx directory.

mkdir -p components/navbar && touch components/navbar/reveal.tsx

Paste the code

Open the newly created file and paste the following code:

"use client";
 
import { cn } from "@/lib/utils";
import {
  motion,
  useMotionValueEvent,
  useScroll,
  useTransform,
  useMotionValue,
  AnimatePresence,
} from "framer-motion";
import { useEffect, useRef, useState } from "react";
 
const Reveal = () => {
  const [isHidden, setIsHidden] = useState(false);
  const [height, setHeight] = useState(0);
  const [mounted, setMounted] = useState(false);
  const { scrollY } = useScroll();
  const lastYRef = useRef(0);
 
  const navbarWidth = useMotionValue(65);
  const routesOpacity = useTransform(navbarWidth, [65, 500], [0, 1]);
 
  useEffect(() => {
    setMounted(true);
  }, []);
 
  useMotionValueEvent(scrollY, "change", (y) => {
    const difference = y - lastYRef.current;
 
    if (difference > 50) {
      setIsHidden(false);
    } else {
      setIsHidden(true);
    }
 
    setHeight(difference);
  });
 
  const firstNavVariants = {
    hidden: {
      width: 65,
      background: "transparent",
    },
    vissible: {
      width: 500,
      background: "rgb(0,0,0,0.5)",
    },
  };
 
  const routes = ["Home", "About", "Pricing", "FAQ"];
 
  if (!mounted) return <div>Loading...</div>;
 
  return (
    <div className="h-full w-full center">
      <motion.nav
        animate={height > 50 && !isHidden ? "vissible" : "hidden"}
        whileHover="vissible"
        initial="hidden"
        exit="hidden"
        onFocusCapture={() => setIsHidden(false)}
        variants={firstNavVariants}
        transition={{ duration: 0.25 }}
        className={cn(
          "fixed text-neutral-700 p-[10px] z-[10000000000] h-[65px]  backdrop-blur top-10 left-0 right-0 mx-auto overflow-hidden rounded-lg flex items-center justify-between pr-6"
        )}
        style={{
          width: navbarWidth,
        }}
      >
        <motion.div
          animate={{
            height: 50,
          }}
          className="bg-black rounded-lg max-w-[50px] min-w-[50px] flex items-center justify-center"
        >
          <div className="h-4 rounded w-4 bg-white rotate-45" />
        </motion.div>
        <div className="mr-10" />
        <AnimatePresence>
          {(height >= 0 || !isHidden) && (
            <motion.ul className="flex items-center gap-10">
              {routes.map((route) => (
                <motion.li
                  key={route}
                  className="text-white text-xl cursor-pointer"
                  initial={{ opacity: 0 }}
                  animate={{ opacity: 1 }}
                  style={{
                    opacity: routesOpacity,
                  }}
                >
                  {route}
                </motion.li>
              ))}
            </motion.ul>
          )}
        </AnimatePresence>
      </motion.nav>
      <h1 className="font-semibold text-xl">
        The navbar is up. Hover or scroll to reveal
      </h1>
    </div>
  );
};
 
export default Reveal;

Credits

Built by Bossadi Zenith