# Header Three

> A payment-product header with grouped navigation menus and a responsive mobile drawer.

A shadcn/ui block from the [@navui](https://ui.navdeepsingh.dev) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/navui/header-three).

- Page, with a live preview: https://shadcn.exchange/r/navui/header-three
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/navui/header-three-light-48e531f534392593.png
- Registry item: https://ui.navdeepsingh.dev/r/header-three.json
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.navdeepsingh.dev/r/header-three.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `button`, `navigation-menu`

## Files

### `src/registry/blocks/header/header-three/header-three.tsx`

```tsx
'use client'

import Link from 'next/link'
import {
  ArrowRight,
  BarChart3,
  BookOpen,
  Building2,
  ChevronDown,
  LayoutDashboard,
  Menu,
  NfcIcon,
  PlugZap,
  ShieldCheck,
  Users,
  X,
} from 'lucide-react'
import React from 'react'

import { Button } from '@/components/ui/button'
import {
  NavigationMenu,
  NavigationMenuContent,
  NavigationMenuItem,
  NavigationMenuLink,
  NavigationMenuList,
  NavigationMenuTrigger,
} from '@/components/ui/navigation-menu'
import { cn } from '@/lib/utils'

const menuItems = [
  {
    name: 'Features',
    href: '#features',
    children: [
      {
        name: 'Dashboard',
        description: 'Track payments and revenue',
        href: '#dashboard',
        icon: LayoutDashboard,
      },
      {
        name: 'Integrations',
        description: 'Connect your payment stack',
        href: '#integrations',
        icon: PlugZap,
      },
      {
        name: 'Security',
        description: 'Built-in fraud protection',
        href: '#security',
        icon: ShieldCheck,
      },
    ],
  },
  {
    name: 'Solutions',
    href: '#solutions',
    children: [
      {
        name: 'Startups',
        description: 'Launch payments faster',
        href: '#startups',
        icon: Building2,
      },
      {
        name: 'Teams',
        description: 'Manage payment operations',
        href: '#teams',
        icon: Users,
      },
      {
        name: 'Analytics',
        description: 'Understand your growth',
        href: '#analytics',
        icon: BarChart3,
      },
    ],
  },
  { name: 'Pricing', href: '#pricing' },
  { name: 'Docs', href: '#docs', icon: BookOpen },
]

export default function HeaderThree() {
  const [menuState, setMenuState] = React.useState(false)
  const [isScrolled, setIsScrolled] = React.useState(false)
  const [openDropdown, setOpenDropdown] = React.useState('')
  const [mobileDropdown, setMobileDropdown] = React.useState<string | null>(null)

  React.useEffect(() => {
    const handleScroll = () => {
      setIsScrolled(window.scrollY > 24)
    }

    handleScroll()

    window.addEventListener('scroll', handleScroll, { passive: true })

    return () => window.removeEventListener('scroll', handleScroll)
  }, [])

  const toggleMobileDropdown = (name: string) => {
    setMobileDropdown((current) => (current === name ? null : name))
  }

  const toggleMobileMenu = () => {
    const nextMenuState = !menuState

    setMenuState(nextMenuState)

    if (!nextMenuState) {
      setMobileDropdown(null)
    }
  }

  const closeMobileMenu = () => {
    setMenuState(false)
    setMobileDropdown(null)
  }

  return (
    <header>
      <nav
        data-state={menuState && 'active'}
        className="fixed inset-x-0 top-0 z-50 w-full px-4 sm:px-6 lg:px-8"
      >
        <div
          className={cn(
            'mx-auto mt-3 w-full max-w-7xl rounded-xl border border-transparent bg-transparent px-0 transition-[max-width,padding,background-color,border-color,box-shadow,backdrop-filter] duration-250 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none',
            isScrolled &&
              'max-w-6xl border-border/60 bg-background/70 px-3 shadow-sm shadow-black/5 backdrop-blur-xl dark:bg-background/55 dark:shadow-none',
          )}
        >
          <div
            className={cn(
              'relative flex flex-wrap items-center justify-between gap-6 transition-[padding] duration-250 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none lg:gap-0',
              isScrolled ? 'py-2 lg:py-2.5' : 'py-4 lg:py-5',
            )}
          >
            <div className="flex w-full items-center justify-between lg:w-auto">
              <Link href="#" aria-label="home" className="flex items-center gap-2">
                <NfcIcon
                  aria-hidden="true"
                  className={cn(
                    'transition-[width,height] duration-250 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none',
                    isScrolled ? 'size-5' : 'size-6',
                  )}
                />
                <span
                  className={cn(
                    'duration-250e-[cubic-bezier(0.23,1,0.32,1)] font-medium transition-[font-size] motion-reduce:transition-none',
                    isScrolled ? 'text-sm' : 'text-base',
                  )}
                >
                  Payflow
                </span>
              </Link>

              <button
                type="button"
                onClick={toggleMobileMenu}
                aria-label={menuState ? 'Close Menu' : 'Open Menu'}
                aria-expanded={menuState}
                aria-controls="header-three-mobile-menu"
                className="relative z-20 -m-2.5 -mr-2 block cursor-pointer p-2.5 lg:hidden"
              >
                <Menu
                  aria-hidden="true"
                  className="m-auto size-6 transition-[transform,opacity] duration-200 in-data-[state=active]:scale-0 in-data-[state=active]:rotate-180 in-data-[state=active]:opacity-0 motion-reduce:transition-none"
                />
                <X
                  aria-hidden="true"
                  className="absolute inset-0 m-auto size-6 scale-0 -rotate-180 opacity-0 transition-[transform,opacity] duration-200 in-data-[state=active]:scale-100 in-data-[state=active]:rotate-0 in-data-[state=active]:opacity-100 motion-reduce:transition-none"
                />
              </button>
            </div>

            {/* Desktop center nav */}
            <div className="absolute inset-0 m-auto hidden size-fit lg:block">
              <NavigationMenu
                value={openDropdown}
                onValueChange={setOpenDropdown}
                delayDuration={0}
                skipDelayDuration={0}
                className={cn(
                  'text-sm transition-transform duration-250 ease-[cubic-bezier(0.77,0,0.175,1)] motion-reduce:transition-none',
                  isScrolled && 'scale-[0.98]',
                )}
              >
                <NavigationMenuList className="gap-2">
                  {menuItems.map((item) => (
                    <NavigationMenuItem key={item.name} value={item.name}>
                      {item.children ? (
                        <>
                          <NavigationMenuTrigger className="h-auto gap-1 rounded-lg bg-transparent px-3 py-2 text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground focus:bg-muted data-[state=open]:bg-muted data-[state=open]:text-foreground [&>svg:last-child]:hidden">
                            {item.name}
                            <ChevronDown
                              aria-hidden="true"
                              className={cn(
                                'size-3.5 transition-transform duration-200 motion-reduce:transition-none',
                                openDropdown === item.name && 'rotate-180',
                              )}
                            />
                          </NavigationMenuTrigger>

                          <NavigationMenuContent className="w-72 p-2 md:w-72">
                            {item.children.map((child) => {
                              const Icon = child.icon

                              return (
                                <NavigationMenuLink key={child.name} asChild>
                                  <Link
                                    href={child.href}
                                    className="flex cursor-pointer items-start gap-3 rounded-lg p-3 transition-colors outline-none hover:bg-accent focus:bg-accent focus-visible:ring-2 focus-visible:ring-ring/50"
                                  >
                                    <span className="mt-0.5 rounded-md border bg-background p-1.5">
                                      <Icon aria-hidden="true" className="size-4" />
                                    </span>

                                    <span className="space-y-1">
                                      <span className="block text-sm font-medium">
                                        {child.name}
                                      </span>
                                      <span className="block text-xs leading-5 text-muted-foreground">
                                        {child.description}
                                      </span>
                                    </span>
                                  </Link>
                                </NavigationMenuLink>
                              )
                            })}
                          </NavigationMenuContent>
                        </>
                      ) : (
                        <NavigationMenuLink asChild>
                          <Link
                            href={item.href}
                            className="block rounded-lg px-3 py-2 text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground"
                          >
                            {item.name}
                          </Link>
                        </NavigationMenuLink>
                      )}
                    </NavigationMenuItem>
                  ))}
                </NavigationMenuList>
              </NavigationMenu>
            </div>

            {/* Mobile menu + CTA */}
            <div
              id="header-three-mobile-menu"
              className="mx-auto mb-6 hidden w-full max-w-md flex-wrap items-center justify-center space-y-6 rounded-3xl border bg-background p-6 shadow-2xl shadow-zinc-300/20 in-data-[state=active]:block md:flex-nowrap lg:m-0 lg:flex lg:w-fit lg:max-w-none lg:justify-end lg:gap-6 lg:space-y-0 lg:border-transparent lg:bg-transparent lg:p-0 lg:shadow-none lg:in-data-[state=active]:flex dark:shadow-none dark:lg:bg-transparent"
            >
              <div className="w-full lg:hidden">
                <ul className="space-y-2 text-base">
                  {menuItems.map((item) => (
                    <li key={item.name}>
                      {item.children ? (
                        <div>
                          <button
                            type="button"
                            onClick={() => toggleMobileDropdown(item.name)}
                            aria-expanded={mobileDropdown === item.name}
                            aria-controls={`header-three-${item.name.toLowerCase()}-menu`}
                            className="flex w-full items-center justify-between rounded-xl px-3 py-3 text-left font-medium text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground"
                          >
                            <span>{item.name}</span>

                            <ChevronDown
                              aria-hidden="true"
                              className={cn(
                                'size-4 transition-transform duration-200 motion-reduce:transition-none',
                                mobileDropdown === item.name && 'rotate-180',
                              )}
                            />
                          </button>

                          <div
                            id={`header-three-${item.name.toLowerCase()}-menu`}
                            className={cn(
                              'grid overflow-hidden transition-[grid-template-rows,opacity] duration-200 ease-[cubic-bezier(0.77,0,0.175,1)] motion-reduce:transition-none',
                              mobileDropdown === item.name
                                ? 'grid-rows-[1fr] opacity-100'
                                : 'grid-rows-[0fr] opacity-0',
                            )}
                          >
                            <div className="min-h-0">
                              <div className="space-y-1 px-3 pt-1 pb-2">
                                {item.children.map((child) => {
                                  const Icon = child.icon

                                  return (
                                    <Link
                                      key={child.name}
                                      href={child.href}
                                      onClick={closeMobileMenu}
                                      className="flex items-center gap-3 rounded-xl px-3 py-2.5 text-sm text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground"
                                    >
                                      <Icon aria-hidden="true" className="size-4" />
                                      <span>{child.name}</span>
                                    </Link>
                                  )
                                })}
                              </div>
                            </div>
                          </div>
                        </div>
                      ) : (
                        <Link
                          href={item.href}
                          onClick={closeMobileMenu}
                          className="block rounded-xl px-3 py-3 font-medium text-muted-foreground transition-colors duration-150 hover:bg-muted hover:text-foreground"
                        >
                          {item.name}
                        </Link>
                      )}
                    </li>
                  ))}
                </ul>
              </div>

              <div className="flex w-full flex-col sm:w-auto">
                <Button
                  asChild
                  size="sm"
                  className={cn(
                    'h-9 rounded-full px-4 transition-[height,padding,font-size] duration-250 ease-[cubic-bezier(0.23,1,0.32,1)] motion-reduce:transition-none sm:w-auto',
                    isScrolled && 'lg:h-8 lg:px-3 lg:text-xs',
                  )}
                >
                  <Link href="#get-started" onClick={closeMobileMenu}>
                    <span>Get Started</span>
                    <ArrowRight aria-hidden="true" className="size-3.5 ml-1" />
                  </Link>
                </Button>
              </div>
            </div>
          </div>
        </div>
      </nav>
    </header>
  )
}
```
