A minimalist rounded floating header component with backdrop blur, customizable navigation links, action buttons, integrated light/dark theme toggle, and mobile responsive menu dropdown.
1"use client";23import * as React from "react";4import Link from "next/link";5import { Moon, Sun, Menu, X } from "lucide-react";6import { useTheme } from "@/components/theme-provider";7import { cn } from "@/lib/utils";8import { Button } from "@/components/ui/button";9import { Separator } from "@/components/ui/separator";1011const navigationItems = [12 { label: "Home", href: "#home" },13 { label: "About", href: "#about" },14 { label: "Services", href: "#services" },15];1617export type MinimalRoundedHeaderProps = {18 variant?: "desktop" | "compact";19 className?: string;20 homeHref?: string;21 signInHref?: string;22 getStartedHref?: string;23 onMenuClick?: () => void;24};2526export function MinimalRoundedHeader({27 className,28 homeHref = "/",29 signInHref = "/login",30 getStartedHref = "/signup",31 onMenuClick,32}: MinimalRoundedHeaderProps) {33 const { theme, setTheme } = useTheme();34 const [isMobileMenuOpen, setIsMobileMenuOpen] = React.useState(false);3536 const toggleTheme = () => setTheme(theme === "dark" ? "light" : "dark");37 const toggleMobileMenu = () => {38 setIsMobileMenuOpen((prev) => !prev);39 onMenuClick?.();40 };4142 return (43 <header className={cn("relative z-50 w-full px-3 pt-4 md:px-6", className)}>44 <div className="mx-auto max-w-6xl rounded-full border border-border/80 bg-background/80 px-2.5 py-2 shadow-[0_12px_40px_rgba(15,23,42,0.06)] backdrop-blur-xl">45 <div className="flex items-center justify-between gap-3">46 <Link47 href={homeHref}48 aria-label="UDX home"49 className="group flex items-center gap-2 rounded-full px-2 py-1.5 transition-colors hover:bg-accent/60"50 >51 <div className="flex h-8 w-8 items-center justify-center rounded-full border border-border/80 bg-muted/60 shadow-inner shadow-white/40">52 <svg53 className="h-4 w-4 text-foreground shrink-0"54 viewBox="0 0 24 24"55 fill="none"56 xmlns="http://www.w3.org/2000/svg"57 >58 <rect x="3" y="3" width="18" height="18" rx="5" className="fill-primary/10 stroke-primary" strokeWidth="1.5" />59 <path d="M7 8H17M7 12H17M7 16H13" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" />60 </svg>61 </div>6263 <div className="hidden sm:flex flex-col items-start leading-none">64 <span className="text-[11px] font-bold tracking-[0.18em] text-foreground uppercase">UDX</span>65 <span className="mt-0.5 text-[8px] font-medium tracking-[0.22em] text-muted-foreground uppercase">UI Kit</span>66 </div>67 </Link>6869 <nav aria-label="Primary navigation" className="hidden items-center gap-1 rounded-full border border-border/70 bg-muted/30 p-1 md:flex">70 {navigationItems.map((item) => (71 <Button72 key={item.label}73 variant="ghost"74 size="sm"75 render={<Link href={item.href} className="rounded-full px-2.5" />}76 className={cn(77 "rounded-full px-3 text-sm font-medium",78 item.label === "Home" ? "bg-accent text-foreground" : "text-muted-foreground hover:text-foreground",79 )}80 >81 {item.label}82 </Button>83 ))}84 </nav>8586 <div className="flex items-center gap-2">87 <Button88 size="sm"89 variant="default"90 render={<Link href={getStartedHref} className="rounded-[inherit]" />}91 className="hidden sm:inline-flex"92 >93 Get Started94 </Button>95 <Button96 size="sm"97 variant="outline"98 render={<Link href={signInHref} className="rounded-[inherit]" />}99 className="hidden sm:inline-flex"100 >101 Login102 </Button>103104 <Button105 type="button"106 onClick={toggleTheme}107 aria-label={`Switch to ${theme === "dark" ? "light" : "dark"} mode`}108 variant="ghost"109 size="icon-sm"110 className="rounded-full border border-border/70 bg-muted/30 hover:bg-accent"111 >112 {theme === "dark" ? (113 <Sun className="h-[17px] w-[17px] stroke-[1.8]" />114 ) : (115 <Moon className="h-[17px] w-[17px] stroke-[1.8]" />116 )}117 </Button>118119 <Button120 type="button"121 onClick={toggleMobileMenu}122 aria-label={isMobileMenuOpen ? "Close menu" : "Open menu"}123 variant="ghost"124 size="icon-sm"125 className="rounded-full border border-border/70 bg-muted/30 hover:bg-accent md:hidden"126 >127 {isMobileMenuOpen ? <X className="h-[17px] w-[17px]" /> : <Menu className="h-[17px] w-[17px]" />}128 </Button>129 </div>130 </div>131 </div>132133 {isMobileMenuOpen && (134 <div className="mx-auto mt-3 max-w-6xl rounded-[28px] border border-border/80 bg-background/90 p-4 shadow-[0_18px_40px_rgba(15,23,42,0.08)] backdrop-blur-xl md:hidden">135 <nav className="flex flex-col gap-2">136 {navigationItems.map((item) => (137 <Button138 key={item.label}139 variant="ghost"140 size="sm"141 render={<Link href={item.href} className="w-full justify-start" />}142 className="justify-start rounded-xl px-3 text-left text-sm font-medium text-muted-foreground hover:text-foreground"143 >144 {item.label}145 </Button>146 ))}147 </nav>148149 <Separator className="my-3" />150151 <div className="flex flex-col gap-2">152 <Button render={<Link href={getStartedHref} className="w-full" />} className="w-full">Get Started</Button>153 <Button variant="outline" render={<Link href={signInHref} className="w-full" />} className="w-full">Login</Button>154 </div>155 </div>156 )}157 </header>158 );159}160161export default MinimalRoundedHeader;