mirror of
https://github.com/jakejarvis/jarv.is.git
synced 2026-10-27 02:16:23 -04:00
Split the scroll shell, home link and theme toggle into small client components so the contact popover markup and icon SVGs render on the server instead of shipping in the client bundle. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
50 lines
1.2 KiB
TypeScript
50 lines
1.2 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
|
|
/** Sticky header wrapper that gains a background once the page is scrolled. */
|
|
const HeaderShell = ({
|
|
className,
|
|
children,
|
|
}: {
|
|
className?: string;
|
|
children: React.ReactNode;
|
|
}) => {
|
|
const [isScrolled, setIsScrolled] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const handleScroll = () => {
|
|
setIsScrolled(window.scrollY > 10);
|
|
};
|
|
|
|
// Check initial scroll position
|
|
handleScroll();
|
|
|
|
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
return () => window.removeEventListener("scroll", handleScroll);
|
|
}, []);
|
|
|
|
return (
|
|
<div
|
|
data-scrolled={isScrolled}
|
|
style={{ viewTransitionName: "persistent-nav" }}
|
|
className={cn(
|
|
"sticky top-0 z-50 w-full",
|
|
"motion-safe:transition-[background-color,backdrop-filter,border-color]",
|
|
"motion-safe:duration-200",
|
|
"bg-background/0 backdrop-blur-none",
|
|
"data-[scrolled=true]:bg-background/80",
|
|
"data-[scrolled=true]:backdrop-blur-md",
|
|
"data-[scrolled=true]:border-b data-[scrolled=true]:border-border/70",
|
|
className,
|
|
)}
|
|
>
|
|
{children}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export { HeaderShell };
|