Files
gridpilot.gg/apps/website/components/landing/AlternatingSection.tsx
2026-01-18 16:43:32 +01:00

131 lines
4.1 KiB
TypeScript

import { useParallax } from "@/hooks/useScrollProgress";
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/primitives/Stack';
import { Text } from '@/ui/Text';
import { useRef } from 'react';
interface AlternatingSectionProps {
heading: string;
description: string | React.ReactNode;
mockup: React.ReactNode;
layout: 'text-left' | 'text-right';
backgroundImage?: string;
backgroundVideo?: string;
}
export function AlternatingSection({
heading,
description,
mockup,
layout,
backgroundImage,
backgroundVideo
}: AlternatingSectionProps) {
const sectionRef = useRef<HTMLElement>(null);
const bgParallax = useParallax(sectionRef, 0.1);
return (
<Stack
as="section"
ref={sectionRef}
position="relative"
overflow="hidden"
bg="graphite-black"
py={{ base: 20, md: 32 }}
className="border-b border-border-gray"
>
{backgroundVideo && (
<Stack
position="absolute"
inset="0"
fullWidth
fullHeight
overflow="hidden"
>
<Stack
as="video"
autoPlay
loop
muted
playsInline
fullWidth
fullHeight
objectFit="cover"
opacity={0.1}
>
<Stack as="source" src={backgroundVideo} type="video/mp4" />
</Stack>
{/* Dark overlay to ensure readability */}
<Stack position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Stack>
)}
{backgroundImage && !backgroundVideo && (
<Stack
position="absolute"
inset="0"
fullWidth
fullHeight
overflow="hidden"
>
<Stack
position="absolute"
inset="0"
bg={`url(${backgroundImage})`}
backgroundSize="cover"
backgroundPosition="center"
opacity={0.1}
style={{ transform: `translateY(${bgParallax * 0.3}px)` }}
/>
{/* Dark overlay to ensure readability */}
<Stack position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Stack>
)}
<Container size="lg" position="relative" zIndex={10}>
<Stack display="grid" gridCols={{ base: 1, lg: 2 }} gap={{ base: 12, lg: 24 }} alignItems="center">
{/* Text Content */}
<Stack
display="flex"
flexDirection="column"
gap={8}
order={{ lg: layout === 'text-right' ? 2 : 1 }}
>
<Stack gap={4}>
<Stack w="8" h="1" bg="primary-accent" />
<Heading level={2} fontSize={{ base: '3xl', md: '5xl' }} weight="bold" className="tracking-tighter uppercase leading-none">
{heading}
</Heading>
</Stack>
<Stack className="text-gray-500 border-l border-border-gray/20 pl-6">
{typeof description === 'string' ? (
<Text size="lg" leading="relaxed" weight="normal">{description}</Text>
) : (
description
)}
</Stack>
</Stack>
{/* Mockup */}
<Stack
position="relative"
order={{ lg: layout === 'text-right' ? 1 : 2 }}
className="bg-panel-gray/20 border border-border-gray/30 rounded-none p-1 shadow-2xl group"
>
<Stack
fullWidth
minHeight={{ base: '240px', md: '380px' }}
className="overflow-hidden rounded-none border border-border-gray/20 bg-graphite-black"
>
{mockup}
</Stack>
{/* Decorative corner accents */}
<Stack position="absolute" top="-1px" left="-1px" w="3" h="3" borderTop borderLeft borderColor="primary-accent/40" />
<Stack position="absolute" bottom="-1px" right="-1px" w="3" h="3" borderBottom borderRight borderColor="primary-accent/40" />
</Stack>
</Stack>
</Container>
</Stack>
);
}