Navbar
NavigationA responsive marketing navbar with logo, links, auth + CTA buttons, and a mobile menu toggle.
bySaumya
1280pxOpen
components/blocks/navbar.tsx
"use client";
import * as React from "react";
import { Menu, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
const links = [
{ label: "Features", href: "#" },
{ label: "Pricing", href: "#" },
{ label: "Docs", href: "#" },
{ label: "Blog", href: "#" },
];
export function Navbar() {
const [open, setOpen] = React.useState(false);
return (
<header className="sticky top-0 z-40 border-b border-border bg-background/80 backdrop-blur-md">
<div className="mx-auto flex h-14 max-w-6xl items-center justify-between px-4 sm:px-6">
<a href="#" className="flex items-center gap-2 font-semibold tracking-tight">
<span className="grid size-6 place-items-center rounded-md bg-accent text-xs font-bold text-accent-fg">
A
</span>
Acme
</a>
<nav className="hidden items-center gap-1 text-sm md:flex">
{links.map((l) => (
<a
key={l.label}
href={l.href}
className="rounded-md px-3 py-1.5 text-muted transition-colors hover:text-foreground"
>
{l.label}
</a>
))}
</nav>
<div className="hidden items-center gap-2 md:flex">
<Button variant="ghost" size="sm">
Sign in
</Button>
<Button size="sm">Get started</Button>
</div>
<button
type="button"
aria-label="Toggle menu"
aria-expanded={open}
onClick={() => setOpen((o) => !o)}
className="inline-flex size-9 items-center justify-center rounded-md text-foreground md:hidden"
>
{open ? <X className="size-5" /> : <Menu className="size-5" />}
</button>
</div>
<div className={cn("border-t border-border md:hidden", open ? "block" : "hidden")}>
<nav className="mx-auto flex max-w-6xl flex-col gap-1 px-4 py-3 text-sm sm:px-6">
{links.map((l) => (
<a
key={l.label}
href={l.href}
className="rounded-md px-3 py-2 text-muted transition-colors hover:bg-surface-2 hover:text-foreground"
>
{l.label}
</a>
))}
<div className="mt-2 flex flex-col gap-2">
<Button variant="outline" className="w-full">
Sign in
</Button>
<Button className="w-full">Get started</Button>
</div>
</nav>
</div>
</header>
);
}Installation
Terminal
npx shadcn@latest add https://ui.saumyarex.xyz/r/navbar.jsonInstalls the block and its component dependencies (button) in one step.
This block uses the button component — add it first.
Install dependencies
Terminal
npm install lucide-react clsx tailwind-mergeCopy the source
components/blocks/navbar.tsx
"use client";
import * as React from "react";
import { Menu, X } from "lucide-react";
import { Button } from "@/components/ui/button";
import { cn } from "@/lib/utils";
const links = [
{ label: "Features", href: "#" },
{ label: "Pricing", href: "#" },
{ label: "Docs", href: "#" },
{ label: "Blog", href: "#" },
];
export function Navbar() {
const [open, setOpen] = React.useState(false);
return (
<header className="sticky top-0 z-40 border-b border-border bg-background/80 backdrop-blur-md">
<div className="mx-auto flex h-14 max-w-6xl items-center justify-between px-4 sm:px-6">
<a href="#" className="flex items-center gap-2 font-semibold tracking-tight">
<span className="grid size-6 place-items-center rounded-md bg-accent text-xs font-bold text-accent-fg">
A
</span>
Acme
</a>
<nav className="hidden items-center gap-1 text-sm md:flex">
{links.map((l) => (
<a
key={l.label}
href={l.href}
className="rounded-md px-3 py-1.5 text-muted transition-colors hover:text-foreground"
>
{l.label}
</a>
))}
</nav>
<div className="hidden items-center gap-2 md:flex">
<Button variant="ghost" size="sm">
Sign in
</Button>
<Button size="sm">Get started</Button>
</div>
<button
type="button"
aria-label="Toggle menu"
aria-expanded={open}
onClick={() => setOpen((o) => !o)}
className="inline-flex size-9 items-center justify-center rounded-md text-foreground md:hidden"
>
{open ? <X className="size-5" /> : <Menu className="size-5" />}
</button>
</div>
<div className={cn("border-t border-border md:hidden", open ? "block" : "hidden")}>
<nav className="mx-auto flex max-w-6xl flex-col gap-1 px-4 py-3 text-sm sm:px-6">
{links.map((l) => (
<a
key={l.label}
href={l.href}
className="rounded-md px-3 py-2 text-muted transition-colors hover:bg-surface-2 hover:text-foreground"
>
{l.label}
</a>
))}
<div className="mt-2 flex flex-col gap-2">
<Button variant="outline" className="w-full">
Sign in
</Button>
<Button className="w-full">Get started</Button>
</div>
</nav>
</div>
</header>
);
}lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
/** Merge conditional class names and resolve Tailwind conflicts. */
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}