All components
Floating Navbar
navigationAceternity UI component.
responsive · 560px
Install
Same command in any shadcn project — React (Vite/CRA), Next.js, Remix, Astro, and more:
$
npx shadcn@latest add https://your-domain/r/floating-navbar.jsonUsage
"use client";
import { FloatingNav } from "@/registry/aceternity-ui/floating-navbar";
const navItems = [
{ name: "Home", link: "#" },
{ name: "About", link: "#about" },
{ name: "Services", link: "#services" },
{ name: "Contact", link: "#contact" },
];
export default function Demo() {
return (
<div className="relative w-full h-[400px] bg-gray-50 dark:bg-gray-950 overflow-hidden">
<FloatingNav navItems={navItems} />
<div className="flex items-center justify-center h-full text-gray-500 text-sm">
Scroll down to reveal the floating navbar
</div>
</div>
);
}Component source
"use client";
import React, { useState } from "react";
import {
motion,
AnimatePresence,
useScroll,
useMotionValueEvent,
} from "motion/react";
import { cn } from "@/lib/utils";
export const FloatingNav = ({
navItems,
className,
}: {
navItems: {
name: string;
link: string;
icon?: JSX.Element;
}[];
className?: string;
}) => {
const { scrollYProgress } = useScroll();
const [visible, setVisible] = useState(false);
useMotionValueEvent(scrollYProgress, "change", (current) => {
if (typeof current === "number") {
const direction = current - scrollYProgress.getPrevious()!;
if (scrollYProgress.get() < 0.05) {
setVisible(false);
} else {
if (direction < 0) {
setVisible(true);
} else {
setVisible(false);
}
}
}
});
return (
<AnimatePresence mode="wait">
<motion.div
initial={{
opacity: 1,
y: -100,
}}
animate={{
y: visible ? 0 : -100,
opacity: visible ? 1 : 0,
}}
transition={{
duration: 0.2,
}}
className={cn(
"flex max-w-fit fixed top-10 inset-x-0 mx-auto z-[5000] items-center justify-center",
className
)}
>
<div className="flex items-center justify-center gap-2 rounded-full border border-white/10 bg-white/80 px-2 py-1.5 shadow-lg shadow-black/10 backdrop-blur-md dark:border-white/10 dark:bg-black/50">
{/* Nav items container */}
<div className="flex items-center gap-1">
{navItems.map((navItem, idx: number) => (
<a
key={`link-${idx}`}
href={navItem.link}
className={cn(
"relative flex items-center gap-1 rounded-full px-4 py-2 text-sm font-medium text-neutral-600 transition-colors hover:bg-neutral-100 hover:text-neutral-900 dark:text-neutral-300 dark:hover:bg-white/10 dark:hover:text-white"
)}
>
<span className="block sm:hidden">{navItem.icon}</span>
<span className="hidden sm:block">{navItem.name}</span>
</a>
))}
</div>
{/* Divider */}
<div className="h-5 w-px bg-neutral-200 dark:bg-white/10" />
{/* CTA Button */}
<button className="relative rounded-full bg-neutral-900 px-4 py-2 text-sm font-medium text-white transition-all hover:bg-neutral-800 hover:shadow-lg hover:shadow-neutral-900/20 dark:bg-white dark:text-black dark:hover:bg-neutral-100 dark:hover:shadow-white/20">
<span>Login</span>
</button>
</div>
</motion.div>
</AnimatePresence>
);
};Dependencies
motion
Source: Aceternity UI