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)).