shadimage
diarmuradi
blockheader-4source: ok · hit

Header 4

npx shadcn add "https://diarmuradi.com/r/header-4.json"
free

Where it goes

navbar

Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.

Dependencies

Bundle weight · medium
iconslucide-react
animationmotion

Registry dependencies

https://www.diarmuradi.com/r/styles/base-nova/button.jsondesktop-navhttps://www.diarmuradi.com/r/styles/base-nova/fancy-button.jsonhttps://www.diarmuradi.com/r/styles/base-nova/icons.jsonmobile-navhttps://www.diarmuradi.com/r/styles/base-nova/navigation-menu.jsonhttps://www.diarmuradi.com/r/styles/base-nova/separator.json

Files3 · source cached 10/8/2026, 9:04:40 PM

header.tsx
"use client"

import Link from "next/link"

import { FancyButton } from "@/components/fancy-button"
import { Icons } from "@/components/icons"
import { DesktopNav } from "@/components/header/header-4/desktop-nav"
import { MobileNav } from "@/components/header/header-4/mobile-nav"

export function SiteHeader() {
  return (
    <header className="sticky top-0 z-50 flex w-full justify-center px-4">
      <div className="relative w-full max-w-xl">
        <div className="grid h-14 grid-cols-[1fr_auto_1fr] items-center gap-2">
          <FancyButton
            size="icon"
            className="justify-self-start"
            render={<Link href="#" />}
          >
            <Icons.Logo className="size-4" />
            <span className="sr-only">Home</span>
          </FancyButton>

          <DesktopNav />

          <div className="flex items-center justify-end gap-2">
            <FancyButton size="lg" className="hidden md:inline-flex">
              Sign in
            </FancyButton>
            <MobileNav />
          </div>
        </div>
      </div>
    </header>
  )
}
desktop-nav.tsx
"use client"

import * as React from "react"
import Link from "next/link"

import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
import { Separator } from "@/components/ui/separator"

export const solutions = [
  {
    key: "insights",
    title: "Insights",
    description: "Deep analytics to help you understand user behavior",
    href: "#solutions/insights",
  },
  {
    key: "workflow",
    title: "Workflow",
    description: "Automate repetitive processes and save time",
    href: "#solutions/workflow",
  },
  {
    key: "crm-pro",
    title: "CRM Pro",
    description: "Manage customer relationships with advanced tools",
    href: "#solutions/crm-pro",
  },
]

export const learnLinks = [
  { href: "#guide/getting-started", title: "Start Guide" },
  { href: "#guide/tutorials", title: "Tutorials" },
  { href: "#guide/api", title: "API Docs" },
]

export const supportLinks = [
  { href: "#help/faq", title: "FAQ" },
  { href: "#help/contact", title: "Contact Support" },
]

export function DesktopNav() {
  return (
    <nav data-header-menu="4" className="hidden md:flex">
      <style>{`
        body:has(nav[data-header-menu="4"] [data-popup-open]) .cn-navigation-menu-popup {
          width: fit-content !important;
          border-radius: var(--radius-4xl) !important;
          background-color: var(--popover) !important;
          box-shadow: var(--shadow-elevated-sm) !important;
          transform: scale(1) !important;
          opacity: 1 !important;
          transition: opacity 300ms cubic-bezier(0.22, 1, 0.36, 1),
            transform 300ms cubic-bezier(0.22, 1, 0.36, 1) !important;
        }
        body:has(nav[data-header-menu="4"] [data-popup-open])
          .cn-navigation-menu-popup[data-starting-style],
        body:has(nav[data-header-menu="4"] [data-popup-open])
          .cn-navigation-menu-popup[data-ending-style] {
          transform: scale(0.95) !important;
          opacity: 0 !important;
        }
        body:has(nav[data-header-menu="4"] [data-popup-open]) .cn-navigation-menu-content,
        body:has(nav[data-header-menu="4"] [data-popup-open])
          .cn-navigation-menu-content[data-starting-style],
        body:has(nav[data-header-menu="4"] [data-popup-open])
          .cn-navigation-menu-content[data-ending-style] {
          width: max-content !important;
          height: auto !important;
          padding: 1rem !important;
          transition: none !important;
          transform: none !important;
          translate: none !important;
          opacity: 1 !important;
        }
      `}</style>
      <NavigationMenu align="center">
        <NavigationMenuList className="gap-2">
          <NavigationMenuItem>
            <NavigationMenuLink
              className="h-8 text-muted-foreground hover:text-foreground focus:text-foreground"
              render={<Link href="#" />}
            >
              Home
            </NavigationMenuLink>
          </NavigationMenuItem>

          <NavigationMenuItem>
            <NavigationMenuTrigger className="h-8 bg-transparent font-normal text-muted-foreground hover:bg-muted hover:text-foreground focus:bg-muted focus:text-foreground data-popup-open:[&_svg]:text-primary">
              Products
            </NavigationMenuTrigger>
            <NavigationMenuContent className="flex w-135! gap-4 p-4!">
              <div className="flex flex-1 flex-col gap-2">
                <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                  Solutions
                </h3>
                <ul className="flex flex-col gap-3">
                  {solutions.map((solution) => (
                    <ListItem
                      key={solution.href}
                      href={solution.href}
                      title={solution.title}
                    >
                      {solution.description}
                    </ListItem>
                  ))}
                </ul>
              </div>
              <Separator orientation="vertical" className="bg-border/50" />
              <div className="flex flex-col gap-2">
                <h4 className="px-2 text-xs font-semibold text-muted-foreground">
                  Quick Links
                </h4>
                <ul className="flex flex-col gap-2">
                  {learnLinks.map((link) => (
                    <ListItem
                      key={link.href}
                      href={link.href}
                      title={link.title}
                    />
                  ))}
                  {supportLinks.map((link) => (
                    <ListItem
                      key={link.href}
                      href={link.href}
                      title={link.title}
                    />
                  ))}
                </ul>
              </div>
            </NavigationMenuContent>
          </NavigationMenuItem>

          <NavigationMenuItem>
            <NavigationMenuTrigger className="h-8 bg-transparent font-normal text-muted-foreground hover:bg-muted hover:text-foreground focus:bg-muted focus:text-foreground data-popup-open:[&_svg]:text-primary">
              Resources
            </NavigationMenuTrigger>
            <NavigationMenuContent className="flex w-110! gap-4 p-4!">
              <div className="flex flex-1 flex-col gap-2">
                <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                  Learning Resources
                </h3>
                <ul className="flex flex-col gap-2">
                  {learnLinks.map((link) => (
                    <ListItem
                      key={link.href}
                      href={link.href}
                      title={link.title}
                    />
                  ))}
                </ul>
              </div>
              <div className="flex flex-col gap-2">
                <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                  Support & Help
                </h3>
                <ul className="flex flex-col gap-2">
                  {supportLinks.map((link) => (
                    <ListItem
                      key={link.href}
                      href={link.href}
                      title={link.title}
                    />
                  ))}
                </ul>
              </div>
            </NavigationMenuContent>
          </NavigationMenuItem>

          <NavigationMenuItem>
            <NavigationMenuLink
              className="h-8 text-muted-foreground hover:text-foreground focus:text-foreground"
              render={<Link href="#pricing" />}
            >
              Pricing
            </NavigationMenuLink>
          </NavigationMenuItem>
        </NavigationMenuList>
      </NavigationMenu>
    </nav>
  )
}

function ListItem({
  title,
  children,
  href,
  ...props
}: React.ComponentPropsWithoutRef<"li"> & { href: string }) {
  return (
    <li {...props}>
      <NavigationMenuLink className="rounded-lg" render={<Link href={href} />}>
        <div className="flex flex-col gap-1">
          <div className="leading-none font-medium">{title}</div>
          {children ? (
            <div className="line-clamp-2 text-muted-foreground">{children}</div>
          ) : null}
        </div>
      </NavigationMenuLink>
    </li>
  )
}
mobile-nav.tsx
"use client"

import * as React from "react"
import Link from "next/link"
import { cn } from "cn"
import { AnimatePresence, motion } from "motion/react"

import { Button } from "@/components/ui/button"
import { Separator } from "@/components/ui/separator"
import {
  learnLinks,
  solutions,
  supportLinks,
} from "@/components/header/header-4/desktop-nav"
import { ChevronDownIcon, EqualIcon, XIcon } from 'lucide-react'

function ListItem({
  title,
  children,
  href,
  onNavigate,
}: {
  title: string
  children?: string
  href: string
  onNavigate: () => void
}) {
  return (
    <Button
      variant="ghost"
      className="h-fit w-full flex-col items-start gap-0.5 py-2 text-muted-foreground hover:text-foreground focus:text-foreground"
      render={<Link href={href} onClick={onNavigate} />}
      nativeButton={false}
    >
      <span className="font-medium">{title}</span>
      {children ? (
        <span className="text-xs text-pretty text-muted-foreground">
          {children}
        </span>
      ) : null}
    </Button>
  )
}

export function MobileNav() {
  const [isOpen, setIsOpen] = React.useState(false)
  const [isProductsOpen, setIsProductsOpen] = React.useState(false)
  const [isResourcesOpen, setIsResourcesOpen] = React.useState(false)

  const closeMenu = () => {
    setIsOpen(false)
    setIsProductsOpen(false)
    setIsResourcesOpen(false)
  }

  return (
    <>
      <Button
        onClick={() => setIsOpen(!isOpen)}
        aria-label={isOpen ? "Close Menu" : "Open Menu"}
        aria-expanded={isOpen}
        variant="ghost"
        size="icon"
        className="size-10 md:hidden *:[&>svg]:size-5"
      >
        {isOpen ? <XIcon /> : <EqualIcon />}
      </Button>

      <AnimatePresence>
        {isOpen && (
          <motion.div
            initial={{ opacity: 0, y: -8 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -8 }}
            transition={{ duration: 0.3, ease: "easeInOut" }}
            className="absolute top-full right-0 left-0 z-50 mt-2 flex max-h-[85vh] flex-col gap-1 overflow-y-auto rounded-4xl bg-popover p-2 shadow-elevated-sm md:hidden"
          >
            <Button
              variant="ghost"
              className="h-8 justify-start text-muted-foreground hover:text-foreground focus:text-foreground"
              render={<Link href="#" onClick={closeMenu} />}
              nativeButton={false}
            >
              Home
            </Button>

            <div className="flex flex-col">
              <Button
                onClick={() => setIsProductsOpen(!isProductsOpen)}
                variant="ghost"
                className="flex h-8 items-center justify-between text-muted-foreground hover:text-foreground focus:text-foreground"
              >
                Products
                <ChevronDownIcon  className={cn(
                    "size-4 transition-transform",
                    isProductsOpen && "rotate-180 text-primary"
                  )} />
              </Button>
              {isProductsOpen && (
                <div className="flex flex-col gap-2 pt-2 pl-3">
                  <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                    Solutions
                  </h3>
                  <div className="flex flex-col gap-3">
                    {solutions.map((solution) => (
                      <ListItem
                        key={solution.href}
                        href={solution.href}
                        title={solution.title}
                        onNavigate={closeMenu}
                      >
                        {solution.description}
                      </ListItem>
                    ))}
                  </div>
                  <Separator className="my-2 bg-border/50" />
                  <h4 className="px-2 text-xs font-semibold text-muted-foreground">
                    Quick Links
                  </h4>
                  <div className="flex flex-col gap-2">
                    {learnLinks.map((link) => (
                      <ListItem
                        key={link.href}
                        href={link.href}
                        title={link.title}
                        onNavigate={closeMenu}
                      />
                    ))}
                    {supportLinks.map((link) => (
                      <ListItem
                        key={link.href}
                        href={link.href}
                        title={link.title}
                        onNavigate={closeMenu}
                      />
                    ))}
                  </div>
                </div>
              )}
            </div>

            <div className="flex flex-col">
              <Button
                onClick={() => setIsResourcesOpen(!isResourcesOpen)}
                variant="ghost"
                className="flex h-8 items-center justify-between text-muted-foreground hover:text-foreground focus:text-foreground"
              >
                Resources
                <ChevronDownIcon  className={cn(
                    "size-4 transition-transform",
                    isResourcesOpen && "rotate-180 text-primary"
                  )} />
              </Button>
              {isResourcesOpen && (
                <div className="flex flex-col gap-2 pt-2 pl-3">
                  <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                    Learning Resources
                  </h3>
                  <div className="flex flex-col gap-2">
                    {learnLinks.map((link) => (
                      <ListItem
                        key={link.href}
                        href={link.href}
                        title={link.title}
                        onNavigate={closeMenu}
                      />
                    ))}
                  </div>
                  <Separator className="my-2 bg-border/50" />
                  <h3 className="px-2 text-xs font-semibold text-muted-foreground">
                    Support & Help
                  </h3>
                  <div className="flex flex-col gap-2">
                    {supportLinks.map((link) => (
                      <ListItem
                        key={link.href}
                        href={link.href}
                        title={link.title}
                        onNavigate={closeMenu}
                      />
                    ))}
                  </div>
                </div>
              )}
            </div>

            <Button
              variant="ghost"
              className="h-8 justify-start text-muted-foreground hover:text-foreground focus:text-foreground"
              render={<Link href="#pricing" onClick={closeMenu} />}
              nativeButton={false}
            >
              Pricing
            </Button>

            <Button className="h-9 w-full md:hidden" onClick={closeMenu}>
              Sign in
            </Button>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  )
}

More from diarmuradi

Browse all components in this library →