Files
Portfolio/src/components/layout/GlobalBackground.tsx
T
damjan_savicandClaude Sonnet 4.5 19d76d47ea fix: add SSR safety and fix memory leak (qa-requested)
- Add 'use client' directive to GlobalBackground component
- Fix SSR-unsafe document access in usePageVisibility hook
- Fix memory leak in useIntersectionObserver cleanup function

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-25 06:41:49 +01:00

137 lines
3.3 KiB
TypeScript

'use client';
import { usePageVisibility } from '@/hooks/usePageVisibility';
import { useIntersectionObserver } from '@/hooks/useIntersectionObserver';
const GlobalBackground = () => {
const isPageVisible = usePageVisibility();
const { ref, isIntersecting } = useIntersectionObserver<HTMLDivElement>({
threshold: 0.1,
rootMargin: '0px'
});
const shouldAnimate = isPageVisible && isIntersecting;
return (
<>
{/* Background layer */}
<div
ref={ref}
className="fixed inset-0 bg-zinc-900"
style={{ zIndex: -2 }}
/>
{/* Gradient overlay */}
<div
className="fixed inset-0"
style={{
zIndex: -1,
background: 'linear-gradient(135deg, #1e1e1e 0%, #2a2a2a 50%, #1e1e1e 100%)',
opacity: 0.9
}}
/>
{/* Animated lines */}
<div
className="fixed inset-0 pointer-events-none"
style={{ zIndex: -1 }}
>
<svg
className="w-full h-full"
preserveAspectRatio="none"
style={{ opacity: 0.3 }}
>
<line
x1="0%"
y1="20%"
x2="100%"
y2="20%"
stroke="white"
strokeWidth="1"
opacity="0.2"
>
{shouldAnimate && (
<>
<animate
attributeName="y1"
values="20%;80%;20%"
dur="10s"
repeatCount="indefinite"
/>
<animate
attributeName="y2"
values="20%;80%;20%"
dur="10s"
repeatCount="indefinite"
/>
</>
)}
</line>
<line
x1="0%"
y1="50%"
x2="100%"
y2="50%"
stroke="white"
strokeWidth="1"
opacity="0.15"
>
{shouldAnimate && (
<animate
attributeName="x1"
values="0%;100%;0%"
dur="15s"
repeatCount="indefinite"
/>
)}
</line>
<line
x1="20%"
y1="0%"
x2="20%"
y2="100%"
stroke="white"
strokeWidth="1"
opacity="0.1"
>
{shouldAnimate && (
<>
<animate
attributeName="x1"
values="20%;80%;20%"
dur="12s"
repeatCount="indefinite"
/>
<animate
attributeName="x2"
values="20%;80%;20%"
dur="12s"
repeatCount="indefinite"
/>
</>
)}
</line>
</svg>
</div>
{/* Grid overlay */}
<div
className="fixed inset-0 pointer-events-none"
style={{
zIndex: -1,
backgroundImage: `
linear-gradient(rgba(255,255,255,.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(255,255,255,.05) 1px, transparent 1px)
`,
backgroundSize: '50px 50px',
opacity: 0.5
}}
/>
</>
);
};
export default GlobalBackground;