Baktiyar Ablaikhan

Resizable Navbar

Source
Aceternity UI ↗
Author
Aceternity UI
Licence
Aceternity UI licence (free component)

Loading…

A full-width navbar shrinks into a floating blurred pill as the page scrolls.

Code

"use client";
import {
  Navbar,
  NavBody,
  NavItems,
  MobileNav,
  NavbarLogo,
  NavbarButton,
  MobileNavHeader,
  MobileNavToggle,
  MobileNavMenu,
} from "@/lab/aceternity/ui/resizable-navbar";
import { useRef, useState } from "react";

const navItems = [
  { name: "Features", link: "#features" },
  { name: "Pricing", link: "#pricing" },
  { name: "Contact", link: "#contact" },
];

export default function NavbarDemo() {
  const scrollRef = useRef<HTMLDivElement>(null);
  const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false);

  return (
    <div ref={scrollRef} className="@container relative h-full w-full overflow-y-auto bg-white dark:bg-neutral-950">
      <Navbar container={scrollRef}>
        {/* Desktop Navigation */}
        <NavBody>
          <NavbarLogo />
          <NavItems items={navItems} />
          <div className="flex items-center gap-4">
            <NavbarButton as="button" variant="secondary">
              Login
            </NavbarButton>
            <NavbarButton as="button" variant="primary">
              Book a call
            </NavbarButton>
          </div>
        </NavBody>

        {/* Mobile Navigation */}
        <MobileNav>
          <MobileNavHeader>
            <NavbarLogo />
            <MobileNavToggle isOpen={isMobileMenuOpen} onClick={() => setIsMobileMenuOpen(!isMobileMenuOpen)} />
          </MobileNavHeader>

          <MobileNavMenu isOpen={isMobileMenuOpen} onClose={() => setIsMobileMenuOpen(false)}>
            {navItems.map((item, idx) => (
              <a
                key={`mobile-link-${idx}`}
                href={item.link}
                onClick={(e) => {
                  e.preventDefault();
                  setIsMobileMenuOpen(false);
                }}
                className="relative text-neutral-600 dark:text-neutral-300"
              >
                <span className="block">{item.name}</span>
              </a>
            ))}
            <div className="flex w-full flex-col gap-4">
              <NavbarButton as="button" onClick={() => setIsMobileMenuOpen(false)} variant="primary" className="w-full">
                Login
              </NavbarButton>
              <NavbarButton as="button" onClick={() => setIsMobileMenuOpen(false)} variant="primary" className="w-full">
                Book a call
              </NavbarButton>
            </div>
          </MobileNavMenu>
        </MobileNav>
      </Navbar>
      <DummyContent />
    </div>
  );
}

const boxes = [
  { id: 1, title: "The", width: "col-span-1" },
  { id: 2, title: "First", width: "col-span-2" },
  { id: 3, title: "Rule", width: "col-span-1" },
  { id: 4, title: "Of", width: "col-span-3" },
  { id: 5, title: "F", width: "col-span-1" },
  { id: 6, title: "Club", width: "col-span-2" },
  { id: 7, title: "Is", width: "col-span-2" },
  { id: 8, title: "You", width: "col-span-1" },
  { id: 9, title: "Do NOT TALK about", width: "col-span-2" },
  { id: 10, title: "F Club", width: "col-span-1" },
];

const DummyContent = () => {
  return (
    <div className="mx-auto p-[4%] pt-16">
      <h1 className="mb-3 text-center text-[clamp(1rem,3.5cqw,1.9rem)] font-bold text-neutral-900 dark:text-neutral-100">
        Scroll to see the navbar resize
      </h1>
      <p className="mb-8 text-center text-[clamp(0.7rem,1.6cqw,0.875rem)] text-zinc-500">
        For this demo the navbar is <span className="font-medium">sticky</span> inside the card.
      </p>
      <div className="grid grid-cols-4 gap-3">
        {boxes.map((box) => (
          <div
            key={box.id}
            className={`${box.width} flex h-[clamp(5rem,18cqw,12rem)] items-center justify-center rounded-lg bg-neutral-100 p-4 text-neutral-800 shadow-sm dark:bg-neutral-800 dark:text-neutral-200`}
          >
            <h2 className="text-center text-[clamp(0.75rem,2cqw,1.25rem)] font-medium">{box.title}</h2>
          </div>
        ))}
      </div>
    </div>
  );
};
Prompt

Build "Resizable Navbar", a navigation animation. What it does: A full-width navbar shrinks into a floating blurred pill as the page scrolls. Write it as a single self-contained React component in TypeScript that fills its parent (w-full h-full), styled with Tailwind CSS, using @tabler/icons-react, motion. Technique: the Motion library. It sits on a light background, in a 16:10 frame. Respect prefers-reduced-motion with a still state, pause work when the element is off screen, and keep it accessible. Original: https://ui.aceternity.com/components/resizable-navbar (Aceternity UI, Aceternity UI licence (free component)).