{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "layouts-scroll-header",
"type": "registry:block",
"title": "Scroll Header",
"description": "Scroll-aware sticky header with fluid animated tab transitions. Ships with home, about, contact, and danger-zone demo pages.",
"dependencies": [
"motion",
"lucide-react",
"next-themes"
],
"registryDependencies": [
"skeleton"
],
"files": [
{
"path": "components/layouts/scroll-header/scroll-header.tsx",
"content": "\"use client\";\n\nimport React from \"react\";\nimport Link from \"next/link\";\nimport { ArrowLeftIcon, Sparkles } from \"lucide-react\";\nimport { motion, useScroll, useSpring, useTransform } from \"motion/react\";\n\nimport { ModeToggle } from \"@/components/mode-toggle\";\nimport { AnimatedTabs } from \"@/components/layouts/scroll-header/animated-tabs\";\n\nconst tabs = [\n { label: \"Home\", value: \"home\", href: \"/preview/layouts/scroll-header\" },\n {\n label: \"About\",\n value: \"about\",\n href: \"/preview/layouts/scroll-header/about\",\n },\n {\n label: \"Contact\",\n value: \"contact\",\n href: \"/preview/layouts/scroll-header/contact\",\n },\n {\n label: \"Danger Zone\",\n value: \"danger-zone\",\n href: \"/preview/layouts/scroll-header/danger-zone\",\n },\n];\n\n// Spring profile tuned for scroll-linked motion: tight, near-critical damping,\n// low mass. Responds quickly, settles cleanly, no visible overshoot.\nconst SCROLL_SPRING = { stiffness: 500, damping: 50, mass: 0.5 } as const;\n\nexport function ScrollHeader() {\n // Read the window scroll position as a motion value (rAF-driven,\n // passive listener, no React state, no re-renders per frame).\n const { scrollY } = useScroll();\n\n // Logo shrink: scale 1 → 0.8 over the first 33px of scroll.\n const logoScaleRaw = useTransform(scrollY, [0, 33], [1, 0.8], {\n clamp: true,\n });\n const logoScale = useSpring(logoScaleRaw, SCROLL_SPRING);\n\n // Tab strip nudges right 0 → 40px over the first 80px of scroll to\n // clear space for the shrunken logo corner.\n const tabXRaw = useTransform(scrollY, [0, 80], [0, 40], { clamp: true });\n const tabX = useSpring(tabXRaw, SCROLL_SPRING);\n\n return (\n <>\n