Gradient Navbar
Original · freegradient navbar
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/navx-gradient.json"use client";
import { useEffect, useId, useRef, useState } from "react";
import type { ReactNode } from "react";
import { AnimatePresence, motion, useReducedMotion } from "motion/react";
type IconProps = { className?: string };
function ChevronIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path
d="M6 9l6 6 6-6"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
function MenuIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path d="M4 7h16M4 12h16M4 17h16" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
);
}
function CloseIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path d="M6 6l12 12M18 6L6 18" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
);
}
function SearchIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<circle cx="11" cy="11" r="7" stroke="currentColor" strokeWidth="2" />
<path d="M20 20l-3.2-3.2" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
);
}
function PulseIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path
d="M3 12h3l2.5-6 4 13 2.5-7H21"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
function ShieldIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path
d="M12 3l7 3v5c0 4.5-3 8-7 10-4-2-7-5.5-7-10V6l7-3z"
stroke="currentColor"
strokeWidth="2"
strokeLinejoin="round"
/>
<path d="M9 12l2 2 4-4" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
function BoltIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path
d="M13 2L4 14h6l-1 8 9-12h-6l1-8z"
stroke="currentColor"
strokeWidth="2"
strokeLinejoin="round"
/>
</svg>
);
}
function LayersIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<path d="M12 3l9 5-9 5-9-5 9-5z" stroke="currentColor" strokeWidth="2" strokeLinejoin="round" />
<path d="M3 13l9 5 9-5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
</svg>
);
}
function GlobeIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<circle cx="12" cy="12" r="9" stroke="currentColor" strokeWidth="2" />
<path
d="M3 12h18M12 3c2.5 2.4 3.8 5.6 3.8 9S14.5 18.6 12 21C9.5 18.6 8.2 15.4 8.2 12S9.5 5.4 12 3z"
stroke="currentColor"
strokeWidth="2"
strokeLinejoin="round"
/>
</svg>
);
}
function UsersIcon({ className }: IconProps) {
return (
<svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
<circle cx="9" cy="8" r="3.2" stroke="currentColor" strokeWidth="2" />
<path d="M3.5 19c.6-3 2.8-4.6 5.5-4.6S13.9 16 14.5 19" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
<path d="M16 5.4A3.2 3.2 0 0119 11m1.5 8c-.3-1.9-1.2-3.3-2.6-4.1" stroke="currentColor" strokeWidth="2" strokeLinecap="round" />
</svg>
);
}
type MegaLink = {
label: string;
description: string;
href: string;
icon: (props: IconProps) => ReactNode;
};
type NavItem =
| { id: string; label: string; href: string; menu?: undefined }
| { id: string; label: string; href?: undefined; menu: MegaLink[] };
const NAV_ITEMS: NavItem[] = [
{
id: "product",
label: "Product",
menu: [
{
label: "Live Metrics",
description: "Sub-second event streams with 90-day retention.",
href: "#live-metrics",
icon: PulseIcon,
},
{
label: "Guardrails",
description: "Anomaly alerts that page the right on-call engineer.",
href: "#guardrails",
icon: ShieldIcon,
},
{
label: "Edge Pipelines",
description: "Transform data in 14 regions before it lands.",
href: "#edge-pipelines",
icon: BoltIcon,
},
{
label: "Warehouse Sync",
description: "One-click reverse ETL to Snowflake and BigQuery.",
href: "#warehouse-sync",
icon: LayersIcon,
},
],
},
{
id: "solutions",
label: "Solutions",
menu: [
{
label: "For Platform Teams",
description: "Ship observability the whole org actually uses.",
href: "#platform-teams",
icon: GlobeIcon,
},
{
label: "For Growth",
description: "Attribute revenue to the events that drive it.",
href: "#growth",
icon: PulseIcon,
},
{
label: "For Enterprise",
description: "SSO, audit logs, and 99.99% uptime SLAs.",
href: "#enterprise",
icon: UsersIcon,
},
],
},
{ id: "pricing", label: "Pricing", href: "#pricing" },
{ id: "docs", label: "Docs", href: "#docs" },
];
export default function NavxGradient() {
const reduce = useReducedMotion();
const rootRef = useRef<HTMLDivElement | null>(null);
const sentinelRef = useRef<HTMLDivElement | null>(null);
const triggerRefs = useRef<Record<string, HTMLButtonElement | null>>({});
const [openMenu, setOpenMenu] = useState<string | null>(null);
const [mobileOpen, setMobileOpen] = useState(false);
const [activeId, setActiveId] = useState<string>("product");
const [query, setQuery] = useState("");
const [elevated, setElevated] = useState(false);
const idPrefix = useId();
useEffect(() => {
const node = sentinelRef.current;
if (!node) return;
const observer = new IntersectionObserver(
([entry]) => setElevated(!entry.isIntersecting),
{ rootMargin: "-4px 0px 0px 0px", threshold: 0 }
);
observer.observe(node);
return () => observer.disconnect();
}, []);
useEffect(() => {
function onPointerDown(event: PointerEvent) {
if (!rootRef.current) return;
if (!rootRef.current.contains(event.target as Node)) {
setOpenMenu(null);
}
}
document.addEventListener("pointerdown", onPointerDown);
return () => document.removeEventListener("pointerdown", onPointerDown);
}, []);
useEffect(() => {
function onKeyDown(event: KeyboardEvent) {
if (event.key !== "Escape") return;
if (openMenu) {
const id = openMenu;
setOpenMenu(null);
triggerRefs.current[id]?.focus();
} else if (mobileOpen) {
setMobileOpen(false);
}
}
document.addEventListener("keydown", onKeyDown);
return () => document.removeEventListener("keydown", onKeyDown);
}, [openMenu, mobileOpen]);
function toggleMenu(id: string) {
setOpenMenu((current) => (current === id ? null : id));
}
const menuMotion = reduce
? { initial: false, animate: {}, exit: {} }
: {
initial: { opacity: 0, y: 8, scale: 0.98 },
animate: { opacity: 1, y: 0, scale: 1 },
exit: { opacity: 0, y: 8, scale: 0.98 },
};
const mobileMotion = reduce
? { initial: false, animate: {}, exit: {} }
: {
initial: { opacity: 0, height: 0 },
animate: { opacity: 1, height: "auto" },
exit: { opacity: 0, height: 0 },
};
return (
<section
className="relative w-full overflow-hidden bg-gradient-to-br from-indigo-700 via-violet-700 to-sky-600 text-white dark:from-slate-950 dark:via-indigo-950 dark:to-slate-900"
>
<style>{`
@keyframes navxgradient-sheen {
0% { transform: translateX(-120%); }
60%, 100% { transform: translateX(220%); }
}
@keyframes navxgradient-orbit {
0% { transform: translate3d(0,0,0) scale(1); opacity: 0.55; }
50% { transform: translate3d(3%, -4%, 0) scale(1.08); opacity: 0.8; }
100% { transform: translate3d(0,0,0) scale(1); opacity: 0.55; }
}
.navxgradient-sheen {
animation: navxgradient-sheen 5.5s ease-in-out infinite;
}
.navxgradient-orbit {
animation: navxgradient-orbit 14s ease-in-out infinite;
}
@media (prefers-reduced-motion: reduce) {
.navxgradient-sheen, .navxgradient-orbit { animation: none !important; }
}
`}</style>
{/* Ambient gradient blobs */}
<div aria-hidden="true" className="pointer-events-none absolute inset-0 overflow-hidden">
<div className="navxgradient-orbit absolute -left-24 -top-32 h-80 w-80 rounded-full bg-sky-400/40 blur-3xl dark:bg-indigo-500/30" />
<div className="navxgradient-orbit absolute -right-16 top-10 h-72 w-72 rounded-full bg-violet-400/40 blur-3xl dark:bg-violet-600/25" />
</div>
<div ref={sentinelRef} className="absolute left-0 top-0 h-px w-full" aria-hidden="true" />
<div ref={rootRef} className="relative z-20">
<nav
aria-label="Primary"
className={[
"sticky top-0 z-30 w-full border-b transition-colors duration-300",
"backdrop-blur-md",
elevated
? "border-white/15 bg-indigo-800/70 shadow-lg shadow-indigo-950/30 dark:border-white/10 dark:bg-slate-950/80"
: "border-white/10 bg-white/5 dark:border-white/5 dark:bg-transparent",
].join(" ")}
>
<div className="mx-auto flex max-w-7xl items-center justify-between gap-4 px-5 py-3.5 sm:px-8">
{/* Brand */}
<a
href="#top"
className="group flex items-center gap-2.5 rounded-xl px-1.5 py-1 outline-none focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950"
>
<span className="relative grid h-9 w-9 place-items-center overflow-hidden rounded-xl bg-white/15 ring-1 ring-inset ring-white/30">
<PulseIcon className="h-5 w-5 text-white" />
<span className="navxgradient-sheen absolute inset-0 w-1/3 -skew-x-12 bg-white/40 blur-md" aria-hidden="true" />
</span>
<span className="text-[1.05rem] font-semibold tracking-tight text-white">
Auralis
</span>
</a>
{/* Desktop nav */}
<ul className="hidden items-center gap-1 lg:flex">
{NAV_ITEMS.map((item) => {
const isActive = activeId === item.id;
if (!item.menu) {
return (
<li key={item.id}>
<a
href={item.href}
aria-current={isActive ? "page" : undefined}
onClick={() => setActiveId(item.id)}
className={[
"relative rounded-lg px-3.5 py-2 text-sm font-medium outline-none transition-colors",
"focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950",
isActive ? "text-white" : "text-indigo-100/85 hover:text-white",
].join(" ")}
>
{item.label}
{isActive ? (
<span className="absolute inset-x-3.5 -bottom-0.5 h-0.5 rounded-full bg-white" aria-hidden="true" />
) : null}
</a>
</li>
);
}
const menuId = `${idPrefix}-menu-${item.id}`;
const isOpen = openMenu === item.id;
return (
<li key={item.id} className="relative">
<button
type="button"
ref={(el) => {
triggerRefs.current[item.id] = el;
}}
aria-haspopup="true"
aria-expanded={isOpen}
aria-controls={menuId}
onClick={() => {
toggleMenu(item.id);
setActiveId(item.id);
}}
className={[
"group flex items-center gap-1.5 rounded-lg px-3.5 py-2 text-sm font-medium outline-none transition-colors",
"focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950",
isOpen ? "text-white" : "text-indigo-100/85 hover:text-white",
].join(" ")}
>
{item.label}
<ChevronIcon
className={[
"h-4 w-4 transition-transform duration-200",
isOpen ? "rotate-180" : "rotate-0",
].join(" ")}
/>
</button>
<AnimatePresence>
{isOpen ? (
<motion.div
key="panel"
id={menuId}
role="group"
aria-label={item.label}
{...menuMotion}
transition={{ duration: reduce ? 0 : 0.18, ease: "easeOut" }}
className="absolute left-1/2 top-[calc(100%+0.6rem)] z-40 w-[26rem] -translate-x-1/2"
>
<div className="overflow-hidden rounded-2xl border border-slate-200 bg-white p-2 shadow-2xl shadow-slate-900/20 ring-1 ring-black/5 dark:border-slate-800 dark:bg-slate-900 dark:ring-white/10">
<ul className="grid gap-1">
{item.menu.map((link) => {
const Icon = link.icon;
return (
<li key={link.href}>
<a
href={link.href}
onClick={() => {
setOpenMenu(null);
setActiveId(item.id);
}}
className="group/link flex items-start gap-3 rounded-xl p-3 outline-none transition-colors hover:bg-indigo-50 focus-visible:ring-2 focus-visible:ring-indigo-500 dark:hover:bg-slate-800/70 dark:focus-visible:ring-indigo-400"
>
<span className="mt-0.5 grid h-9 w-9 shrink-0 place-items-center rounded-lg bg-gradient-to-br from-indigo-500 to-violet-500 text-white shadow-sm">
<Icon className="h-5 w-5" />
</span>
<span className="min-w-0">
<span className="block text-sm font-semibold text-slate-900 dark:text-slate-100">
{link.label}
</span>
<span className="mt-0.5 block text-[0.8rem] leading-snug text-slate-500 dark:text-slate-400">
{link.description}
</span>
</span>
</a>
</li>
);
})}
</ul>
</div>
</motion.div>
) : null}
</AnimatePresence>
</li>
);
})}
</ul>
{/* Right cluster */}
<div className="flex items-center gap-2.5">
<form
role="search"
onSubmit={(event) => event.preventDefault()}
className="hidden items-center xl:flex"
>
<label htmlFor={`${idPrefix}-search`} className="sr-only">
Search Auralis
</label>
<div className="flex items-center gap-2 rounded-xl border border-white/20 bg-white/10 px-3 py-2 focus-within:ring-2 focus-within:ring-white/80">
<SearchIcon className="h-4 w-4 text-indigo-100/80" />
<input
id={`${idPrefix}-search`}
type="search"
value={query}
onChange={(event) => setQuery(event.target.value)}
placeholder="Search docs, metrics…"
className="w-40 bg-transparent text-sm text-white placeholder:text-indigo-100/60 outline-none"
/>
</div>
</form>
<a
href="#signin"
className="hidden rounded-xl px-3.5 py-2 text-sm font-medium text-indigo-100/90 outline-none transition-colors hover:text-white focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950 sm:inline-block"
>
Sign in
</a>
<a
href="#trial"
className="rounded-xl bg-white px-4 py-2 text-sm font-semibold text-indigo-700 shadow-sm outline-none transition-transform hover:scale-[1.03] focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 active:scale-[0.98] dark:text-slate-900 dark:focus-visible:ring-offset-slate-950"
>
Start free trial
</a>
<button
type="button"
aria-label={mobileOpen ? "Close menu" : "Open menu"}
aria-expanded={mobileOpen}
aria-controls={`${idPrefix}-mobile`}
onClick={() => setMobileOpen((v) => !v)}
className="grid h-10 w-10 place-items-center rounded-xl border border-white/20 bg-white/10 text-white outline-none transition-colors hover:bg-white/20 focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950 lg:hidden"
>
{mobileOpen ? <CloseIcon className="h-5 w-5" /> : <MenuIcon className="h-5 w-5" />}
</button>
</div>
</div>
{/* Mobile panel */}
<AnimatePresence>
{mobileOpen ? (
<motion.div
key="mobile"
id={`${idPrefix}-mobile`}
{...mobileMotion}
transition={{ duration: reduce ? 0 : 0.24, ease: "easeInOut" }}
className="overflow-hidden lg:hidden"
>
<div className="mx-auto max-w-7xl space-y-1 px-5 pb-6 pt-2 sm:px-8">
{NAV_ITEMS.map((item) =>
item.menu ? (
<div key={item.id} className="py-1">
<p className="px-3 pb-1 pt-2 text-xs font-semibold uppercase tracking-wide text-indigo-100/70">
{item.label}
</p>
<ul className="space-y-0.5">
{item.menu.map((link) => {
const Icon = link.icon;
return (
<li key={link.href}>
<a
href={link.href}
onClick={() => setMobileOpen(false)}
className="flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm font-medium text-indigo-50 outline-none transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-white/80"
>
<span className="grid h-8 w-8 place-items-center rounded-lg bg-white/15">
<Icon className="h-4.5 w-4.5" />
</span>
{link.label}
</a>
</li>
);
})}
</ul>
</div>
) : (
<a
key={item.id}
href={item.href}
onClick={() => {
setActiveId(item.id);
setMobileOpen(false);
}}
className="block rounded-xl px-3 py-2.5 text-sm font-semibold text-white outline-none transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-white/80"
>
{item.label}
</a>
)
)}
<div className="flex items-center gap-3 pt-3">
<a
href="#signin"
onClick={() => setMobileOpen(false)}
className="flex-1 rounded-xl border border-white/25 px-4 py-2.5 text-center text-sm font-semibold text-white outline-none transition-colors hover:bg-white/10 focus-visible:ring-2 focus-visible:ring-white/80"
>
Sign in
</a>
<a
href="#trial"
onClick={() => setMobileOpen(false)}
className="flex-1 rounded-xl bg-white px-4 py-2.5 text-center text-sm font-semibold text-indigo-700 outline-none transition-colors focus-visible:ring-2 focus-visible:ring-white/80 dark:text-slate-900"
>
Start free trial
</a>
</div>
</div>
</motion.div>
) : null}
</AnimatePresence>
</nav>
{/* Demo hero beneath the bar so the gradient + sticky elevation read in context */}
<div id="top" className="mx-auto max-w-7xl px-5 pb-24 pt-16 sm:px-8 sm:pt-24">
<span className="inline-flex items-center gap-2 rounded-full border border-white/25 bg-white/10 px-3.5 py-1.5 text-xs font-medium text-indigo-50">
<span className="h-1.5 w-1.5 rounded-full bg-emerald-300" aria-hidden="true" />
Now streaming 4.2 billion events / day
</span>
<h1 className="mt-6 max-w-2xl text-4xl font-semibold leading-tight tracking-tight text-white sm:text-5xl">
Observability your whole team reaches for first.
</h1>
<p className="mt-5 max-w-xl text-base leading-relaxed text-indigo-100/85 sm:text-lg">
Auralis turns raw event firehoses into clear, shareable signal — live
dashboards, anomaly guardrails, and warehouse sync, without a single
cron job to babysit.
</p>
<div className="mt-8 flex flex-wrap items-center gap-3">
<a
href="#trial"
className="rounded-xl bg-white px-5 py-3 text-sm font-semibold text-indigo-700 shadow-sm outline-none transition-transform hover:scale-[1.03] focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 active:scale-[0.98] dark:text-slate-900 dark:focus-visible:ring-offset-slate-950"
>
Start free — no card
</a>
<a
href="#tour"
className="rounded-xl border border-white/25 bg-white/5 px-5 py-3 text-sm font-semibold text-white outline-none transition-colors hover:bg-white/15 focus-visible:ring-2 focus-visible:ring-white/80 focus-visible:ring-offset-2 focus-visible:ring-offset-indigo-700 dark:focus-visible:ring-offset-slate-950"
>
Take the 2-min tour
</a>
</div>
</div>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Centred Logo Navbar
OriginalA three-column navbar with the brand logo centred between the primary links and the account actions, wrapped in a soft rounded card.

Left Logo Navbar With CTA
OriginalA classic left-aligned logo navbar with centred navigation links and a prominent pill call-to-action button on the right.

Navbar With Dropdown Menu
OriginalA navbar featuring a JS-free product dropdown built with native details and summary, revealing a two-item mega-menu panel with icons.

Glass Transparent Navbar
OriginalA frosted glass navbar floating over a colourful gradient hero backdrop, using backdrop blur and translucent borders for a modern overlay header.

Responsive Navbar with Mobile Menu
MITA marketing site header with a logo, inline nav links, login/register buttons, and a working hamburger toggle that reveals a stacked mobile menu below the md breakpoint. Fully keyboard/ARIA accessible with light and dark variants.

Underline Tabs
MITAn accessible underline-style tab switcher with a bottom-border active indicator and a live content panel. State-driven with proper role=tablist/tab/tabpanel and aria-selected wiring, styled for light and dark modes.

Split Button Dropdown Menu
MITA split-button control with a chevron trigger that opens a divided action menu, including a destructive delete item. Closes on outside-click and Escape, with a rotating chevron and full ARIA menu roles for both light and dark themes.

Glass Navbar
Originalglassmorphic sticky navbar

Mega Navbar
Originalnavbar with a mega dropdown

Centered Logo Navbar
Originalnavbar with centred logo and split links

Sidebar Toggle Navbar
Originalnavbar with a sidebar toggle

Search Navbar
Originalnavbar with an expanding search

