website refactor

This commit is contained in:
2026-01-18 16:18:18 +01:00
parent 0b301feb61
commit 13567d51af
329 changed files with 4701 additions and 4750 deletions

View File

@@ -1,9 +1,8 @@
import { useParallax } from "@/hooks/useScrollProgress";
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
import { useRef } from 'react';
interface AlternatingSectionProps {
@@ -27,7 +26,7 @@ export function AlternatingSection({
const bgParallax = useParallax(sectionRef, 0.1);
return (
<Box
<Stack
as="section"
ref={sectionRef}
position="relative"
@@ -37,14 +36,14 @@ export function AlternatingSection({
className="border-b border-border-gray"
>
{backgroundVideo && (
<Box
<Stack
position="absolute"
inset="0"
fullWidth
fullHeight
overflow="hidden"
>
<Box
<Stack
as="video"
autoPlay
loop
@@ -55,21 +54,21 @@ export function AlternatingSection({
objectFit="cover"
opacity={0.1}
>
<Box as="source" src={backgroundVideo} type="video/mp4" />
</Box>
<Stack as="source" src={backgroundVideo} type="video/mp4" />
</Stack>
{/* Dark overlay to ensure readability */}
<Box position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Box>
<Stack position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Stack>
)}
{backgroundImage && !backgroundVideo && (
<Box
<Stack
position="absolute"
inset="0"
fullWidth
fullHeight
overflow="hidden"
>
<Box
<Stack
position="absolute"
inset="0"
bg={`url(${backgroundImage})`}
@@ -79,53 +78,53 @@ export function AlternatingSection({
style={{ transform: `translateY(${bgParallax * 0.3}px)` }}
/>
{/* Dark overlay to ensure readability */}
<Box position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Box>
<Stack position="absolute" inset="0" bg="linear-gradient(to bottom, #0C0D0F, transparent, #0C0D0F)" />
</Stack>
)}
<Container size="lg" position="relative" zIndex={10}>
<Box display="grid" gridCols={{ base: 1, lg: 2 }} gap={{ base: 12, lg: 24 }} alignItems="center">
<Stack display="grid" gridCols={{ base: 1, lg: 2 }} gap={{ base: 12, lg: 24 }} alignItems="center">
{/* Text Content */}
<Box
<Stack
display="flex"
flexDirection="column"
gap={8}
order={{ lg: layout === 'text-right' ? 2 : 1 }}
>
<Stack gap={4}>
<Box w="8" h="1" bg="primary-accent" />
<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>
<Box className="text-gray-500 border-l border-border-gray/20 pl-6">
<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
)}
</Box>
</Box>
</Stack>
</Stack>
{/* Mockup */}
<Box
<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"
>
<Box
<Stack
fullWidth
minHeight={{ base: '240px', md: '380px' }}
className="overflow-hidden rounded-none border border-border-gray/20 bg-graphite-black"
>
{mockup}
</Box>
</Stack>
{/* Decorative corner accents */}
<Box position="absolute" top="-1px" left="-1px" w="3" h="3" borderTop borderLeft borderColor="primary-accent/40" />
<Box position="absolute" bottom="-1px" right="-1px" w="3" h="3" borderBottom borderRight borderColor="primary-accent/40" />
</Box>
</Box>
<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>
</Box>
</Stack>
);
}

View File

@@ -1,13 +1,12 @@
'use client';
import { routes } from '@/lib/routing/RouteConfig';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Button } from '@/ui/Button';
import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid';
import { Heading } from '@/ui/Heading';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { LeagueCard } from '@/components/leagues/LeagueCard';
import { TeamCard } from '@/components/teams/TeamCard';
@@ -20,22 +19,22 @@ interface DiscoverySectionProps {
export function DiscoverySection({ viewData }: DiscoverySectionProps) {
return (
<Box py={{ base: 20, md: 32 }} bg="graphite-black" borderBottom borderColor="border-gray/50">
<Stack py={{ base: 20, md: 32 }} bg="graphite-black" borderBottom borderColor="border-gray/50">
<Container size="lg">
<Stack gap={16}>
<Box maxWidth="2xl">
<Box borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={4}>
<Stack maxWidth="2xl">
<Stack borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={4}>
<Text size="xs" weight="bold" color="text-primary-accent" className="uppercase tracking-[0.2em]">
Live Ecosystem
</Text>
</Box>
</Stack>
<Heading level={2} weight="bold" fontSize={{ base: '3xl', md: '4xl' }} className="tracking-tight">
Discover the Grid
</Heading>
<Text size="lg" color="text-gray-400" block mt={6} leading="relaxed">
Explore leagues, teams, and races that make up the GridPilot ecosystem.
</Text>
</Box>
</Stack>
<Grid cols={1} lgCols={3} gap={12}>
{/* Top leagues */}
@@ -95,11 +94,11 @@ export function DiscoverySection({ viewData }: DiscoverySectionProps) {
</Link>
</Stack>
{viewData.upcomingRaces.length === 0 ? (
<Box p={12} border borderStyle="dashed" borderColor="border-gray/30" rounded="none" center bg="panel-gray/10">
<Stack p={12} border borderStyle="dashed" borderColor="border-gray/30" rounded="none" center bg="panel-gray/10">
<Text size="sm" color="text-gray-600" font="mono" uppercase letterSpacing="widest">
No races scheduled.
</Text>
</Box>
</Stack>
) : (
<Stack gap={3}>
{viewData.upcomingRaces.map(race => (
@@ -118,6 +117,6 @@ export function DiscoverySection({ viewData }: DiscoverySectionProps) {
</Grid>
</Stack>
</Container>
</Box>
</Stack>
);
}

View File

@@ -2,10 +2,9 @@
import { useState } from 'react';
import { motion } from 'framer-motion';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { Icon } from '@/ui/Icon';
import { ChevronDown } from 'lucide-react';
@@ -40,7 +39,7 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
const [isOpen, setIsOpen] = useState(false);
return (
<Box
<Stack
as={motion.div}
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
@@ -48,8 +47,8 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
transition={{ delay: index * 0.1 }}
group
>
<Box rounded="none" bg="panel-gray/40" border borderColor="border-gray/50" transition hoverBorderColor="primary-accent/30">
<Box
<Stack rounded="none" bg="panel-gray/40" border borderColor="border-gray/50" transition hoverBorderColor="primary-accent/30">
<Stack
as="button"
onClick={() => setIsOpen(!isOpen)}
fullWidth
@@ -59,14 +58,14 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
minHeight="44px"
className="relative overflow-hidden"
>
<Box display="flex" alignItems="center" justifyContent="between" gap={{ base: 2, md: 4 }}>
<Stack display="flex" alignItems="center" justifyContent="between" gap={{ base: 2, md: 4 }}>
<Stack direction="row" align="center" gap={4}>
<Box w="1" h="4" bg={isOpen ? "primary-accent" : "border-gray"} transition className="group-hover:bg-primary-accent" />
<Stack w="1" h="4" bg={isOpen ? "primary-accent" : "border-gray"} transition className="group-hover:bg-primary-accent" />
<Heading level={3} fontSize={{ base: 'sm', md: 'base' }} weight="bold" color="text-white" groupHoverColor="primary-accent" transition className="tracking-wide">
{faq.question}
</Heading>
</Stack>
<Box
<Stack
as={motion.div}
animate={{ rotate: isOpen ? 180 : 0 }}
transition={{ duration: 0.15, ease: 'easeInOut' }}
@@ -76,10 +75,10 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
flexShrink={0}
>
<Icon icon={ChevronDown} size="full" />
</Box>
</Box>
</Box>
<Box
</Stack>
</Stack>
</Stack>
<Stack
as={motion.div}
initial={false}
animate={{
@@ -92,22 +91,22 @@ function FAQItem({ faq, index }: { faq: typeof faqs[0]; index: number }) {
}}
overflow="hidden"
>
<Box px={{ base: 4, md: 6 }} pb={{ base: 4, md: 6 }} pt={0} ml={5}>
<Stack px={{ base: 4, md: 6 }} pb={{ base: 4, md: 6 }} pt={0} ml={5}>
<Text size="sm" color="text-gray-400" weight="normal" leading="relaxed" className="max-w-2xl">
{faq.answer}
</Text>
</Box>
</Box>
</Box>
</Box>
</Stack>
</Stack>
</Stack>
</Stack>
);
}
export function FAQ() {
return (
<Box as="section" position="relative" py={{ base: 20, md: 32 }} bg="graphite-black" overflow="hidden" borderBottom borderColor="border-gray/50">
<Stack as="section" position="relative" py={{ base: 20, md: 32 }} bg="graphite-black" overflow="hidden" borderBottom borderColor="border-gray/50">
{/* Background image with mask */}
<Box
<Stack
position="absolute"
inset="0"
bg="url(/images/porsche.jpeg)"
@@ -116,23 +115,23 @@ export function FAQ() {
opacity={0.03}
/>
<Box maxWidth="4xl" mx="auto" px={{ base: 4, md: 6 }} position="relative" zIndex={10}>
<Box textAlign="center" mb={{ base: 12, md: 16 }}>
<Box borderLeft borderRight borderStyle="solid" borderColor="primary-accent" px={4} display="inline-block" mb={4}>
<Stack maxWidth="4xl" mx="auto" px={{ base: 4, md: 6 }} position="relative" zIndex={10}>
<Stack textAlign="center" mb={{ base: 12, md: 16 }}>
<Stack borderLeft borderRight borderStyle="solid" borderColor="primary-accent" px={4} display="inline-block" mb={4}>
<Text size="xs" weight="bold" color="text-primary-accent" className="uppercase tracking-[0.2em]">
Support & Information
</Text>
</Box>
</Stack>
<Heading level={2} fontSize={{ base: '3xl', md: '4xl' }} weight="bold" color="text-white" mb={4} className="tracking-tight">
Frequently Asked Questions
</Heading>
</Box>
<Box display="flex" flexDirection="column" gap={4}>
</Stack>
<Stack display="flex" flexDirection="column" gap={4}>
{faqs.map((faq, index) => (
<FAQItem key={faq.question} faq={faq} index={index} />
))}
</Box>
</Box>
</Box>
</Stack>
</Stack>
</Stack>
);
}

View File

@@ -4,9 +4,8 @@ import { Section } from '@/ui/Section';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { MockupStack } from '@/components/mockups/MockupStack';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { LeagueHomeMockup } from '@/components/mockups/LeagueHomeMockup';
import { StandingsTableMockup } from '@/components/mockups/StandingsTableMockup';
import { TeamCompetitionMockup } from '@/components/mockups/TeamCompetitionMockup';
@@ -49,30 +48,30 @@ const features = [
function FeatureCard({ feature, index }: { feature: typeof features[0], index: number }) {
return (
<Box
<Stack
display="flex"
flexDirection="column"
gap={6}
className="p-8 bg-panel-gray/20 border border-border-gray/20 rounded-none hover:border-primary-accent/20 transition-all duration-300 ease-smooth group relative overflow-hidden"
>
<Box aspectRatio="video" fullWidth position="relative" className="bg-graphite-black rounded-none overflow-hidden border border-border-gray/20">
<Stack aspectRatio="video" fullWidth position="relative" className="bg-graphite-black rounded-none overflow-hidden border border-border-gray/20">
<MockupStack index={index}>
<feature.MockupComponent />
</MockupStack>
</Box>
</Stack>
<Stack gap={4}>
<Box display="flex" alignItems="center" gap={3}>
<Box w="1" h="3" bg="primary-accent" />
<Stack display="flex" alignItems="center" gap={3}>
<Stack w="1" h="3" bg="primary-accent" />
<Heading level={3} weight="bold" fontSize="lg" className="tracking-tighter uppercase">
{feature.title}
</Heading>
</Box>
</Stack>
<Text size="sm" color="text-gray-500" leading="relaxed" weight="normal" className="group-hover:text-gray-400 transition-colors">
{feature.description}
</Text>
</Stack>
{/* Subtle hover effect */}
<Box
<Stack
position="absolute"
bottom="0"
left="0"
@@ -81,7 +80,7 @@ function FeatureCard({ feature, index }: { feature: typeof features[0], index: n
bg="primary-accent"
className="scale-x-0 group-hover:scale-x-100 transition-transform duration-500 origin-left"
/>
</Box>
</Stack>
);
}
@@ -90,25 +89,25 @@ export function FeatureGrid() {
<Section className="bg-graphite-black border-b border-border-gray/20 py-32">
<Container position="relative" zIndex={10}>
<Stack gap={16}>
<Box maxWidth="2xl">
<Box borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={4} bg="primary-accent/5" py={1}>
<Stack maxWidth="2xl">
<Stack borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={4} bg="primary-accent/5" py={1}>
<Text size="xs" weight="bold" color="text-primary-accent" className="uppercase tracking-[0.3em]">
Engineered for Competition
</Text>
</Box>
</Stack>
<Heading level={2} weight="bold" fontSize={{ base: '3xl', md: '5xl' }} className="tracking-tighter uppercase leading-none">
Building for League Racing
</Heading>
<Text size="lg" color="text-gray-500" block mt={6} leading="relaxed" className="border-l border-border-gray/20 pl-6">
Every feature is designed to reduce friction and increase immersion. Join our Discord to help shape the future of the platform.
</Text>
</Box>
</Stack>
<Box display="grid" gridCols={{ base: 1, md: 2, lg: 3 }} gap={6}>
<Stack display="grid" gridCols={{ base: 1, md: 2, lg: 3 }} gap={6}>
{features.map((feature, index) => (
<FeatureCard key={feature.title} feature={feature} index={index} />
))}
</Box>
</Stack>
</Stack>
</Container>
</Section>

View File

@@ -1,10 +1,9 @@
import { useRef } from 'react';
import { useParallax } from '@/hooks/useScrollProgress';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Button } from '@/ui/Button';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Glow } from '@/ui/Glow';
@@ -15,7 +14,7 @@ export function LandingHero() {
const bgParallax = useParallax(sectionRef, 0.2);
return (
<Box
<Stack
as="section"
ref={sectionRef}
position="relative"
@@ -26,7 +25,7 @@ export function LandingHero() {
className="border-b border-border-gray"
>
{/* Background image layer with parallax */}
<Box
<Stack
position="absolute"
inset="0"
backgroundImage="url(/images/header.jpeg)"
@@ -37,13 +36,13 @@ export function LandingHero() {
/>
{/* Robust gradient overlay */}
<Box
<Stack
position="absolute"
inset="0"
bg="linear-gradient(to bottom, #0C0D0F 0%, transparent 50%, #0C0D0F 100%)"
/>
<Box
<Stack
position="absolute"
inset="0"
bg="radial-gradient(circle at center, transparent 0%, #0C0D0F 100%)"
@@ -55,11 +54,11 @@ export function LandingHero() {
<Container size="lg" position="relative" zIndex={10}>
<Stack gap={{ base: 8, md: 12 }}>
<Stack gap={6} maxWidth="3xl">
<Box borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={2} bg="primary-accent/5" py={1}>
<Stack borderLeft borderStyle="solid" borderColor="primary-accent" pl={4} mb={2} bg="primary-accent/5" py={1}>
<Text size="xs" weight="bold" color="text-primary-accent" uppercase letterSpacing="0.3em">
Precision Racing Infrastructure
</Text>
</Box>
</Stack>
<Heading
level={1}
fontSize={{ base: '4xl', sm: '5xl', md: '6xl', lg: '8xl' }}
@@ -75,7 +74,7 @@ export function LandingHero() {
</Text>
</Stack>
<Box display="flex" flexDirection={{ base: 'column', sm: 'row' }} gap={4}>
<Stack display="flex" flexDirection={{ base: 'column', sm: 'row' }} gap={4}>
<Button
as="a"
href={discordUrl}
@@ -101,10 +100,10 @@ export function LandingHero() {
>
Explore Leagues
</Button>
</Box>
</Stack>
{/* Problem list - more professional */}
<Box
<Stack
display="grid"
gridCols={{ base: 1, sm: 2, lg: 4 }}
gap={8}
@@ -122,20 +121,20 @@ export function LandingHero() {
{ label: 'COMMUNITY', text: 'Built for teams and leagues', color: 'green' }
].map((item) => (
<Stack key={item.label} gap={3} group cursor="default">
<Box display="flex" alignItems="center" gap={3}>
<Box w="1" h="3" bg={item.color === 'primary' ? 'primary-accent' : item.color === 'aqua' ? 'telemetry-aqua' : item.color === 'amber' ? 'warning-amber' : 'success-green'} />
<Stack display="flex" alignItems="center" gap={3}>
<Stack w="1" h="3" bg={item.color === 'primary' ? 'primary-accent' : item.color === 'aqua' ? 'telemetry-aqua' : item.color === 'amber' ? 'warning-amber' : 'success-green'} />
<Text size="xs" weight="bold" color="text-gray-500" uppercase letterSpacing="0.2em" groupHoverTextColor="white" transition>
{item.label}
</Text>
</Box>
</Stack>
<Text size="sm" color="text-gray-500" groupHoverTextColor="gray-300" transition leading="relaxed">
{item.text}
</Text>
</Stack>
))}
</Box>
</Stack>
</Stack>
</Container>
</Box>
</Stack>
);
}