Nav Bar

Smooth animated navigation with colorful hover effects. Customizable colors

navBar/demo.tsx
"use client";
 
import { useState } from "react";
import { AnimatePresence, motion } from "motion/react";
import Link from "next/link";
 
interface NavBarProps {
  tabs?: { label: string; href: string }[];
  colors?: string[];
}
 
const defaultTabs: { label: string; href: string }[] = [
  { label: "Home", href: "/" },
  { label: "Blogs", href: "/" },
  { label: "About", href: "/" },
];
export function NavBar({ tabs, colors }: NavBarProps) {
  const defaultColors = [
    "#FF0080", // Vivid Pink
    "#FFDE00", // Vivid Yellow
    "#32FF7A", // Neon Green
    "#00CFFF", // Bright Blue
    "#FF3D00", // Vibrant Orange-Red
    "#FF61A6", // Disco Pink
    "#8A2BE2", // Blue Violet
    "#FFD300", // Bright Gold
    "#FF6F00", // Vivid Orange
    "#21D4FD", // Light Neon Blue
    "#A259FF", // Purple
    "#FEE440", // Disco Yellow
    "#00FFB0", // Neon Aqua
    "#FD5E53", // Disco Coral
    "#46C3DB", // Cyan
  ];
 
  type TabRef = HTMLButtonElement | null;
  const [tabRefs, _] = useState<TabRef[]>([]);
 
  const [hoveredIdx, setHoveredIdx] = useState<number | null>(null);
  const hoveredTab = tabRefs[hoveredIdx ?? -1]?.getBoundingClientRect();
  const randomColor = colors
    ? colors[Math.floor(Math.random() * colors.length)]
    : defaultColors[Math.floor(Math.random() * defaultColors.length)];
 
  return (
    <nav
      onMouseLeave={() => {
      setHoveredIdx(null);
      }}
      className="bg-background flex items-center relative p-2"
    >
      {tabs
        ? tabs.map((tab, index) => (
            <button
              ref={(el) => {
                tabRefs[index] = el;
              }}
              key={tab.label}
              className="px-2.5 py-1.5 z-10 font-medium cursor-pointer "
              onPointerEnter={() => setHoveredIdx(index)}
            >
              <Link href={tab.href}> {tab.label}</Link>
            </button>
          ))
        : defaultTabs.map((tab, index) => (
            <button
              ref={(el) => {
                tabRefs[index] = el;
              }}
              key={tab.label}
              className="px-2.5 py-1.5 z-10 font-medium cursor-pointer "
              onPointerEnter={() => setHoveredIdx(index)}
            >
              <Link href={tab.href}> {tab.label} </Link>
            </button>
          ))}
      <AnimatePresence>
        {hoveredTab ? (
          <motion.button
            className={`fixed top-0 left-0 rounded-full`}
            style={{
              backgroundColor: `${randomColor}`,
            }}
            initial={{
              top: hoveredTab.top,
              left: hoveredTab.left,
              width: hoveredTab.width,
              height: hoveredTab.height,
              opacity: 0,
            }}
            animate={{
              top: hoveredTab.top,
              left: hoveredTab.left,
              width: hoveredTab.width,
              height: hoveredTab.height,
              opacity: 1,
            }}
            transition={{
              duration: 0.17,
            }}
          />
        ) : null}
      </AnimatePresence>
    </nav>
  );
}

Packages

npm i motion

Props

PropTypeDefaultDescription
tabs{label: string, href: string}[]Default tabsArray of tab objects with label and href
colorsstring[]Default colorsArray of hex color codes for hover effects

Usage

<NavBar 
  tabs={[
    { label: "Home", href: "/" },
    { label: "About", href: "/about" },
    { label: "Contact", href: "/contact" }
  ]}
/>
 
 
<NavBar 
  tabs={[
    { label: "Dashboard", href: "/dashboard" },
    { label: "Settings", href: "/settings" }
  ]}
  colors={["#FF0080", "#00CFFF", "#32FF7A"]}
/>