# Header 2: mega menu with mobile sheet

> Sticky header with brand, a mega menu of grouped links and a featured card, sign-in and primary actions. On phones the same links open in a slide-in sheet with accordions.

A shadcn/ui block from the [@ballmac](https://ui.ballmac.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/ballmac/header-2).

- Page, with a live preview: https://shadcn.exchange/r/ballmac/header-2
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/ballmac/header-2-light-8140978bfa4b834d.png
- Registry item: https://ui.ballmac.com/r/header-2.json
- Categories: blocks, header
- Listed: 2026-10-14, source last changed 2026-10-14

## Install

```bash
npx shadcn@latest add https://ui.ballmac.com/r/header-2.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: `utils`, `https://ui.ballmac.com/r/button.json`, `https://ui.ballmac.com/r/mega-menu.json`, `https://ui.ballmac.com/r/sheet.json`

## Files

### `registry/ballmac/components/blocks/header-2/header-2.tsx`

```tsx
// Ballmac UI: Header 2. https://ui.ballmac.com/blocks/header-2
"use client"

import * as React from "react"
import { BarChart3, Blocks, BookOpen, Code2, Layers, LifeBuoy, Menu, ShieldCheck, Sparkles, Users, Workflow } from "lucide-react"

import { buttonVariants } from "@/components/ballmac/button"
import { MegaMenu, MegaMenuMobileList, type MegaMenuItem } from "@/components/ballmac/mega-menu"
import { Sheet, SheetBody, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger } from "@/components/ballmac/sheet"
import { cn } from "@/lib/utils"

type Action = { label: string; href: string }

type Header2Props = React.ComponentProps<"header"> & {
  /** Brand name beside the logo mark. */
  brand?: string
  /** Where the brand links to. */
  brandHref?: string
  /** Logo mark. Defaults to a simple rounded square with the brand's first letter. */
  logo?: React.ReactNode
  /** Navigation: links, or panels with grouped links and an optional featured card. */
  items?: MegaMenuItem[]
  /** Quiet action on the right, e.g. sign in. */
  secondaryAction?: Action
  /** Main action on the right. */
  primaryAction?: Action
  /** Stick to the top of the page with a blurred background. */
  sticky?: boolean
}

const defaultItems: MegaMenuItem[] = [
  {
    label: "Product",
    columns: [
      {
        title: "Build",
        links: [
          { title: "Workspaces", href: "#", description: "Projects, files and approvals in one place.", icon: <Layers /> },
          { title: "Automations", href: "#", description: "Run tasks when things change.", icon: <Workflow />, badge: "New" },
          { title: "API", href: "#", description: "Build on the same data.", icon: <Code2 /> },
        ],
      },
      {
        title: "Run",
        links: [
          { title: "Analytics", href: "#", description: "Usage and performance at a glance.", icon: <BarChart3 /> },
          { title: "Security", href: "#", description: "Roles, audit logs and sign-in policies.", icon: <ShieldCheck /> },
          { title: "Integrations", href: "#", description: "Connect the tools you already use.", icon: <Blocks /> },
        ],
      },
    ],
    featured: { title: "What’s new", description: "See the latest releases and what they change for your team.", href: "#", media: <Sparkles />, cta: "Read the changelog" },
  },
  {
    label: "Solutions",
    columns: [
      {
        links: [
          { title: "Startups", href: "#", description: "Move fast with a small team.", icon: <Users /> },
          { title: "Enterprise", href: "#", description: "Controls for larger organizations.", icon: <ShieldCheck /> },
        ],
      },
    ],
  },
  {
    label: "Resources",
    columns: [
      {
        links: [
          { title: "Documentation", href: "#", description: "Guides and API reference.", icon: <BookOpen /> },
          { title: "Help center", href: "#", description: "Answers from our support team.", icon: <LifeBuoy /> },
        ],
      },
    ],
  },
  { label: "Pricing", href: "#" },
]

function Header2({
  brand = "Acme",
  brandHref = "#",
  logo,
  items = defaultItems,
  secondaryAction = { label: "Sign in", href: "#" },
  primaryAction = { label: "Get started", href: "#" },
  sticky = true,
  className,
  ...props
}: Header2Props) {
  const [open, setOpen] = React.useState(false)
  return (
    <header data-slot="header-2" className={cn("bg-background/80 z-40 w-full border-b backdrop-blur-xl", sticky && "sticky top-0", className)} {...props}>
      <div className="mx-auto flex h-16 max-w-6xl items-center gap-6 px-4 sm:px-6">
        <a href={brandHref} className="focus-visible:ring-ring/50 flex items-center gap-2.5 rounded-md text-lg font-semibold tracking-tight outline-none focus-visible:ring-[3px]">
          {logo ?? (
            <span aria-hidden="true" className="bg-foreground text-background flex size-7 items-center justify-center rounded-lg text-sm font-bold">
              {brand[0]}
            </span>
          )}
          {brand}
        </a>
        <MegaMenu items={items} label="Main" viewportAlign="start" />
        <div className="ms-auto hidden items-center gap-2 md:flex">
          <a className={buttonVariants({ variant: "ghost" })} href={secondaryAction.href}>{secondaryAction.label}</a>
          <a className={buttonVariants({ shape: "pill" })} href={primaryAction.href}>{primaryAction.label}</a>
        </div>
        <Sheet open={open} onOpenChange={setOpen}>
          <SheetTrigger className={buttonVariants({ variant: "ghost", size: "icon", className: "ms-auto md:hidden" })} aria-label="Open menu">
            <Menu />
          </SheetTrigger>
          <SheetContent side="end" closeLabel="Close menu" className="w-[min(22rem,90vw)]">
            <SheetHeader>
              <SheetTitle>{brand}</SheetTitle>
              <SheetDescription className="sr-only">Site navigation</SheetDescription>
            </SheetHeader>
            <SheetBody>
              <MegaMenuMobileList items={items} onNavigate={() => setOpen(false)} />
            </SheetBody>
            <SheetFooter className="grid gap-2">
              <a className={buttonVariants({ shape: "pill", size: "lg" })} href={primaryAction.href}>{primaryAction.label}</a>
              <a className={buttonVariants({ variant: "outline", shape: "pill", size: "lg" })} href={secondaryAction.href}>{secondaryAction.label}</a>
            </SheetFooter>
          </SheetContent>
        </Sheet>
      </div>
    </header>
  )
}

export { Header2, type Header2Props }
```
