# Header 1

> Responsive sticky header with scroll blur effect, animated mobile menu, and adaptive navigation links.

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

- Page, with a live preview: https://shadcn.exchange/r/efferd/header-1
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/efferd/header-1-light-79c2356ba2db13c6.png
- Registry item: https://efferd.com/r/header-1.json
- Categories: header
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://efferd.com/r/header-1.json
```

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

## Dependencies

- Registry items: `@efferd/logo`, `@efferd/portal`, `button`, `@efferd/use-scroll`

## Files

### `registry/blocks/header/1/header.tsx`

```tsx
"use client";
import { cn } from "@/lib/utils";
import { Logo } from "@/components/logo";
import { useScroll } from "@/hooks/use-scroll";
import { Button } from "@/components/ui/button";
import { MobileNav } from "@/components/mobile-nav";

export const navLinks = [
	{
		label: "Features",
		href: "#",
	},
	{
		label: "Pricing",
		href: "#",
	},
	{
		label: "About",
		href: "#",
	},
];

export function Header() {
	const scrolled = useScroll(10);

	return (
		<header
			className={cn("sticky top-0 z-50 w-full border-transparent border-b", {
				"border-border bg-background/95 backdrop-blur-sm supports-backdrop-filter:bg-background/50":
					scrolled,
			})}
		>
			<nav className="mx-auto flex h-14 w-full max-w-5xl items-center justify-between px-4">
				<a
					className="rounded-md p-2 hover:bg-muted dark:hover:bg-muted/50"
					href="#"
				>
					<Logo className="h-4" />
				</a>
				<div className="hidden items-center gap-2 md:flex">
					{navLinks.map((link) => (
						<Button asChild key={link.label} size="sm" variant="ghost">
							<a href={link.href}>{link.label}</a>
						</Button>
					))}
					<Button size="sm" variant="outline">
						Sign In
					</Button>
					<Button size="sm">Get Started</Button>
				</div>
				<MobileNav />
			</nav>
		</header>
	);
}
```

### `registry/blocks/header/1/mobile-nav.tsx`

```tsx
import { cn } from "@/lib/utils";
import React from "react";
import { Button } from "@/components/ui/button";
import { Portal, PortalBackdrop } from "@/components/portal";
import { navLinks } from "@/components/header";

export function MobileNav() {
	const [open, setOpen] = React.useState(false);

	return (
		<div className="md:hidden">
			<Button
				aria-controls="mobile-menu"
				aria-expanded={open}
				aria-label="Toggle menu"
				className="md:hidden"
				onClick={() => setOpen(!open)}
				size="icon"
				variant="outline"
			>
				{open ? (
					<IconPlaceholder
						className="size-4.5"
						hugeicons="Cancel01Icon"
						lucide="XIcon"
						phosphor="XIcon"
						remixicon="RiCloseLine"
						tabler="IconX"
					/>
				) : (
					<IconPlaceholder
						className="size-4.5"
						hugeicons="Menu01Icon"
						lucide="MenuIcon"
						phosphor="ListIcon"
						remixicon="RiMenuLine"
						tabler="IconMenu2"
					/>
				)}
			</Button>
			{open && (
				<Portal className="top-14" id="mobile-menu">
					<PortalBackdrop />
					<div
						className={cn(
							"data-[slot=open]:zoom-in-97 ease-out data-[slot=open]:animate-in",
							"size-full p-4"
						)}
						data-slot={open ? "open" : "closed"}
					>
						<div className="grid gap-y-2">
							{navLinks.map((link) => (
								<Button
									asChild
									className="justify-start"
									key={link.label}
									variant="ghost"
								>
									<a href={link.href}>{link.label}</a>
								</Button>
							))}
						</div>
						<div className="mt-12 flex flex-col gap-2">
							<Button className="w-full" variant="outline">
								Sign In
							</Button>
							<Button className="w-full">Get Started</Button>
						</div>
					</div>
				</Portal>
			)}
		</div>
	);
}
```
