John Doe
john@example.com
This is a navbar component built using nextjs
Install the required dependencies:
npm install framer-motionimport { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
"use client";
import Link from "next/link";
import React, { useState, useRef } from "react";
const buttonItems = [
{ index: 1, name: "Button 1", link: "#" },
{ index: 2, name: "Button 2", link: "#" },
{ index: 3, name: "Button 3", link: "#" },
{ index: 4, name: "Button 4", link: "#" },
{ index: 5, name: "Button 5", link: "#" },
];
export default function Navbar() {
const [active, setActive] = useState(0);
const [hover, setHover] = useState(-1);
const containerRef = useRef<HTMLDivElement | null>(null);
const itemRefs = useRef<(HTMLAnchorElement | null)[]>([]);
const getStyle = () => {
if (hover < 0) {
return { left: "4px", width: "98.5%" };
}
const item = itemRefs.current[hover];
if (!item || !containerRef.current) return {};
const itemRect = item.getBoundingClientRect();
const parentRect = containerRef.current.getBoundingClientRect();
return {
left: `${itemRect.left - parentRect.left}px`,
width: `${itemRect.width}px`,
};
};
return (
<nav className="w-full h-fit flex justify-center items-center">
<div className="relative p-[3px] inset-[3px] rounded-full bg-gradient-to-b from-neutral-700 to-neutral-800">
<div
ref={containerRef}
className="relative w-fit rounded-full bg-gradient-to-b from-neutral-800 to-neutral-900 h-14 flex items-center"
>
<div
className="absolute top-[5px] h-[46px] bg-gradient-to-b from-white/10 to-white/5 rounded-full transition-all duration-300"
style={getStyle()}
/>
<div className="flex z-10 gap-1">
{buttonItems.map((item) => (
<Link
href={item.link}
key={item.index}
ref={(el) => {
itemRefs.current[item.index] = el;
}}
onMouseEnter={() => setHover(item.index)}
onMouseLeave={() => setHover(-1)}
onClick={() => setActive(item.index)}
className="relative cursor-pointer px-6 mx-1 py-3 z-10"
>
<p
className={`transition-colors duration-200 ${
active === item.index ? "text-black" : "text-white"
}`}
>
{item.name}
</p>
</Link>
))}
</div>
</div>
</div>
</nav>
);
}
Usecase
* Navbar with some animations