diff --git a/apps/website/app/layout.tsx b/apps/website/app/layout.tsx
index a22de4009..c882b6c53 100644
--- a/apps/website/app/layout.tsx
+++ b/apps/website/app/layout.tsx
@@ -6,7 +6,7 @@ import React from 'react';
import './globals.css';
import { AppWrapper } from '@/components/AppWrapper';
import { Header } from '@/ui/Header';
-import { HeaderContent } from '@/ui/HeaderContent';
+import { HeaderContent } from '@/components/layout/HeaderContent';
import { MainContent } from '@/ui/MainContent';
export const dynamic = 'force-dynamic';
diff --git a/apps/website/app/leagues/LeaguesClient.tsx b/apps/website/app/leagues/LeaguesClient.tsx
index 44ccdce84..90b1569dc 100644
--- a/apps/website/app/leagues/LeaguesClient.tsx
+++ b/apps/website/app/leagues/LeaguesClient.tsx
@@ -18,7 +18,7 @@ import {
Target,
Timer,
} from 'lucide-react';
-import { LeagueCard } from '@/ui/LeagueCardWrapper';
+import { LeagueCard } from '@/components/leagues/LeagueCardWrapper';
import { Button } from '@/ui/Button';
import { Card } from '@/ui/Card';
import { Input } from '@/ui/Input';
diff --git a/apps/website/app/leagues/[id]/stewarding/StewardingTemplate.tsx b/apps/website/app/leagues/[id]/stewarding/StewardingTemplate.tsx
index 77d0100d1..8e02db512 100644
--- a/apps/website/app/leagues/[id]/stewarding/StewardingTemplate.tsx
+++ b/apps/website/app/leagues/[id]/stewarding/StewardingTemplate.tsx
@@ -19,7 +19,7 @@ import {
} from 'lucide-react';
import Link from 'next/link';
import { useMemo, useState } from 'react';
-import { PendingProtestsList } from '@/ui/PendingProtestsList';
+import { PendingProtestsList } from '@/components/leagues/PendingProtestsList';
import { PenaltyHistoryList } from '@/components/leagues/PenaltyHistoryList';
interface StewardingData {
diff --git a/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/page.tsx b/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/page.tsx
index f2de7bc85..40f014c7c 100644
--- a/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/page.tsx
+++ b/apps/website/app/leagues/[id]/stewarding/protests/[protestId]/page.tsx
@@ -37,7 +37,7 @@ import { useMemo, useState } from 'react';
// Shared state components
import { StateContainer } from '@/components/shared/state/StateContainer';
-import { LoadingWrapper } from '@/ui/LoadingWrapper';
+import { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';
import { useLeagueAdminStatus } from "@/lib/hooks/league/useLeagueAdminStatus";
import { useProtestDetail } from "@/lib/hooks/league/useProtestDetail";
diff --git a/apps/website/app/sponsor/signup/page.tsx b/apps/website/app/sponsor/signup/page.tsx
index c8a91b798..ada21f254 100644
--- a/apps/website/app/sponsor/signup/page.tsx
+++ b/apps/website/app/sponsor/signup/page.tsx
@@ -5,7 +5,7 @@ import { motion, useReducedMotion } from 'framer-motion';
import { Card } from '@/ui/Card';
import { Button } from '@/ui/Button';
import { Input } from '@/ui/Input';
-import { SponsorHero } from '@/ui/SponsorHero';
+import { SponsorHero } from '@/components/sponsors/SponsorHero';
import { SponsorWorkflowMockup } from '@/components/sponsors/SponsorWorkflowMockup';
import { SponsorBenefitCard } from '@/components/sponsors/SponsorBenefitCard';
import { siteConfig } from '@/lib/siteConfig';
diff --git a/apps/website/ui/AchievementGrid.tsx b/apps/website/components/achievements/AchievementGrid.tsx
similarity index 100%
rename from apps/website/ui/AchievementGrid.tsx
rename to apps/website/components/achievements/AchievementGrid.tsx
diff --git a/apps/website/components/auth/AuthWorkflowMockup.tsx b/apps/website/components/auth/AuthWorkflowMockup.tsx
index 6f5654b4c..b0aacdbfe 100644
--- a/apps/website/components/auth/AuthWorkflowMockup.tsx
+++ b/apps/website/components/auth/AuthWorkflowMockup.tsx
@@ -8,7 +8,7 @@ import {
Trophy,
Car,
} from 'lucide-react';
-import { WorkflowMockup, WorkflowStep } from '@/ui/WorkflowMockup';
+import { WorkflowMockup, WorkflowStep } from '@/components/mockups/WorkflowMockup';
const WORKFLOW_STEPS: WorkflowStep[] = [
{
diff --git a/apps/website/ui/DashboardHeroWrapper.tsx b/apps/website/components/dashboard/DashboardHeroWrapper.tsx
similarity index 100%
rename from apps/website/ui/DashboardHeroWrapper.tsx
rename to apps/website/components/dashboard/DashboardHeroWrapper.tsx
diff --git a/apps/website/ui/QuickActions.tsx b/apps/website/components/dashboard/QuickActions.tsx
similarity index 83%
rename from apps/website/ui/QuickActions.tsx
rename to apps/website/components/dashboard/QuickActions.tsx
index 9d76fd8ff..54a198cbc 100644
--- a/apps/website/ui/QuickActions.tsx
+++ b/apps/website/components/dashboard/QuickActions.tsx
@@ -2,9 +2,9 @@
import { routes } from '@/lib/routing/RouteConfig';
import { Trophy, Users } from 'lucide-react';
-import { Box } from './Box';
-import { Heading } from './Heading';
-import { QuickActionItem } from './QuickActionItem';
+import { Box } from '@/ui/Box';
+import { Heading } from '@/ui/Heading';
+import { QuickActionItem } from '@/ui/QuickActionItem';
export function QuickActions() {
return (
diff --git a/apps/website/ui/DebugModeToggle.tsx b/apps/website/components/dev/DebugModeToggle.tsx
similarity index 98%
rename from apps/website/ui/DebugModeToggle.tsx
rename to apps/website/components/dev/DebugModeToggle.tsx
index 847417120..52f02678f 100644
--- a/apps/website/ui/DebugModeToggle.tsx
+++ b/apps/website/components/dev/DebugModeToggle.tsx
@@ -6,11 +6,11 @@ import type { GlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler
import { getGlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';
import { Bug, Shield, X } from 'lucide-react';
import { useCallback, useEffect, useState } from 'react';
-import { Box } from './Box';
-import { Button } from './Button';
-import { Icon } from './Icon';
-import { Stack } from './Stack';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Button } from '@/ui/Button';
+import { Icon } from '@/ui/Icon';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
// Extend Window interface for debug globals
declare global {
diff --git a/apps/website/ui/DriverCard.tsx b/apps/website/components/drivers/DriverCard.tsx
similarity index 95%
rename from apps/website/ui/DriverCard.tsx
rename to apps/website/components/drivers/DriverCard.tsx
index 2fbdf464d..fa981f88a 100644
--- a/apps/website/ui/DriverCard.tsx
+++ b/apps/website/components/drivers/DriverCard.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import { Card } from '@/ui/Card';
import { RankBadge } from '@/ui/RankBadge';
-import { DriverIdentity } from '@/ui/DriverIdentity';
+import { DriverIdentity } from '@/components/drivers/DriverIdentity';
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
import { Stack } from '@/ui/Stack';
import { DriverStats } from '@/ui/DriverStats';
diff --git a/apps/website/ui/DriverEntryRow.tsx b/apps/website/components/drivers/DriverEntryRow.tsx
similarity index 92%
rename from apps/website/ui/DriverEntryRow.tsx
rename to apps/website/components/drivers/DriverEntryRow.tsx
index fead0fdb4..62bc60cf1 100644
--- a/apps/website/ui/DriverEntryRow.tsx
+++ b/apps/website/components/drivers/DriverEntryRow.tsx
@@ -2,12 +2,12 @@
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
import { Zap } from 'lucide-react';
-import { Badge } from './Badge';
-import { Box } from './Box';
-import { Icon } from './Icon';
-import { Image } from './Image';
-import { Stack } from './Stack';
-import { Text } from './Text';
+import { Badge } from '@/ui/Badge';
+import { Box } from '@/ui/Box';
+import { Icon } from '@/ui/Icon';
+import { Image } from '@/ui/Image';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
interface DriverEntryRowProps {
index: number;
diff --git a/apps/website/ui/DriverIdentity.tsx b/apps/website/components/drivers/DriverIdentity.tsx
similarity index 88%
rename from apps/website/ui/DriverIdentity.tsx
rename to apps/website/components/drivers/DriverIdentity.tsx
index b918ac041..49aeb4d83 100644
--- a/apps/website/ui/DriverIdentity.tsx
+++ b/apps/website/components/drivers/DriverIdentity.tsx
@@ -1,9 +1,9 @@
import Link from 'next/link';
-import Image from 'next/image';
-import { PlaceholderImage } from './PlaceholderImage';
-import { Box } from './Box';
-import { Text } from './Text';
-import { Badge } from './Badge';
+import { PlaceholderImage } from '@/ui/PlaceholderImage';
+import { Box } from '@/ui/Box';
+import { Text } from '@/ui/Text';
+import { Badge } from '@/ui/Badge';
+import { Image } from '@/ui/Image';
export interface DriverIdentityProps {
driver: {
@@ -43,7 +43,9 @@ export function DriverIdentity(props: DriverIdentityProps) {
alt={driver.name}
width={avatarSize}
height={avatarSize}
- className="w-full h-full object-cover"
+ fullWidth
+ fullHeight
+ objectFit="cover"
/>
) : (
diff --git a/apps/website/components/drivers/DriverProfile.tsx b/apps/website/components/drivers/DriverProfile.tsx
index 5d34e9417..f02da4a81 100644
--- a/apps/website/components/drivers/DriverProfile.tsx
+++ b/apps/website/components/drivers/DriverProfile.tsx
@@ -7,10 +7,10 @@ import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { StatCard } from '@/ui/StatCard';
-import { ProfileHeader } from '@/ui/ProfileHeader';
+import { ProfileHeader } from '@/components/drivers/ProfileHeader';
import { ProfileStats } from './ProfileStats';
import { CareerHighlights } from '@/ui/CareerHighlights';
-import { DriverRankings } from '@/ui/DriverRankings';
+import { DriverRankings } from '@/components/drivers/DriverRankings';
import { PerformanceMetrics } from '@/ui/PerformanceMetrics';
import { useDriverProfile } from "@/hooks/driver/useDriverProfile";
diff --git a/apps/website/ui/DriverRankings.tsx b/apps/website/components/drivers/DriverRankings.tsx
similarity index 86%
rename from apps/website/ui/DriverRankings.tsx
rename to apps/website/components/drivers/DriverRankings.tsx
index 16bcead10..acc198ce0 100644
--- a/apps/website/ui/DriverRankings.tsx
+++ b/apps/website/components/drivers/DriverRankings.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
-import { RankingListItem } from '@/ui/RankingListItem';
-import { RankingList } from '@/ui/RankingList';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { RankingListItem } from '@/components/leaderboards/RankingListItem';
+import { RankingList } from '@/components/leaderboards/RankingList';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
export interface DriverRanking {
type: 'overall' | 'league';
diff --git a/apps/website/ui/DriverSummaryPillWrapper.tsx b/apps/website/components/drivers/DriverSummaryPillWrapper.tsx
similarity index 100%
rename from apps/website/ui/DriverSummaryPillWrapper.tsx
rename to apps/website/components/drivers/DriverSummaryPillWrapper.tsx
diff --git a/apps/website/ui/FeaturedDriverCard.tsx b/apps/website/components/drivers/FeaturedDriverCard.tsx
similarity index 100%
rename from apps/website/ui/FeaturedDriverCard.tsx
rename to apps/website/components/drivers/FeaturedDriverCard.tsx
diff --git a/apps/website/ui/ProfileHeader.tsx b/apps/website/components/drivers/ProfileHeader.tsx
similarity index 100%
rename from apps/website/ui/ProfileHeader.tsx
rename to apps/website/components/drivers/ProfileHeader.tsx
diff --git a/apps/website/ui/ProfileHero.tsx b/apps/website/components/drivers/ProfileHero.tsx
similarity index 98%
rename from apps/website/ui/ProfileHero.tsx
rename to apps/website/components/drivers/ProfileHero.tsx
index cca864612..ffcef5320 100644
--- a/apps/website/ui/ProfileHero.tsx
+++ b/apps/website/components/drivers/ProfileHero.tsx
@@ -1,6 +1,7 @@
import { mediaConfig } from '@/lib/config/mediaConfig';
+import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { Heading } from '@/ui/Heading';
diff --git a/apps/website/components/drivers/ProfileRaceHistory.tsx b/apps/website/components/drivers/ProfileRaceHistory.tsx
index bcf9d1761..557afb09d 100644
--- a/apps/website/components/drivers/ProfileRaceHistory.tsx
+++ b/apps/website/components/drivers/ProfileRaceHistory.tsx
@@ -6,8 +6,8 @@ import { Button } from '@/ui/Button';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
-import { LoadingWrapper } from '@/ui/LoadingWrapper';
-import { EmptyState } from '@/ui/EmptyState';
+import { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import { Pagination } from '@/ui/Pagination';
import { Trophy } from 'lucide-react';
diff --git a/apps/website/components/errors/ApiErrorBoundary.tsx b/apps/website/components/errors/ApiErrorBoundary.tsx
index 3efc70380..d942d27aa 100644
--- a/apps/website/components/errors/ApiErrorBoundary.tsx
+++ b/apps/website/components/errors/ApiErrorBoundary.tsx
@@ -3,7 +3,7 @@
import React, { Component, ReactNode, useState } from 'react';
import { ApiError } from '@/lib/api/base/ApiError';
import { connectionMonitor } from '@/lib/api/base/ApiConnectionMonitor';
-import { ErrorDisplay } from './ErrorDisplay';
+import { ErrorDisplay } from '@/components/shared/state/ErrorDisplay';
import { DevErrorPanel } from './DevErrorPanel';
interface Props {
diff --git a/apps/website/components/errors/EnhancedErrorBoundary.tsx b/apps/website/components/errors/EnhancedErrorBoundary.tsx
index 601f05a67..a38f51b67 100644
--- a/apps/website/components/errors/EnhancedErrorBoundary.tsx
+++ b/apps/website/components/errors/EnhancedErrorBoundary.tsx
@@ -4,7 +4,7 @@ import React, { Component, ReactNode, ErrorInfo, useState, version } from 'react
import { ApiError } from '@/lib/api/base/ApiError';
import { getGlobalErrorHandler } from '@/lib/infrastructure/GlobalErrorHandler';
import { DevErrorPanel } from './DevErrorPanel';
-import { ErrorDisplay } from './ErrorDisplay';
+import { ErrorDisplay } from '@/components/shared/state/ErrorDisplay';
interface Props {
children: ReactNode;
diff --git a/apps/website/components/errors/ErrorDisplay.tsx b/apps/website/components/errors/ErrorDisplay.tsx
index 9baa4d8dc..4349fed1d 100644
--- a/apps/website/components/errors/ErrorDisplay.tsx
+++ b/apps/website/components/errors/ErrorDisplay.tsx
@@ -2,7 +2,7 @@
import React from 'react';
import { ApiError } from '@/lib/api/base/ApiError';
-import { ErrorDisplay as UiErrorDisplay } from '@/ui/ErrorDisplay';
+import { ErrorDisplay as UiErrorDisplay } from '@/components/shared/state/ErrorDisplay';
interface ErrorDisplayProps {
error: ApiError;
diff --git a/apps/website/ui/ActivityFeed.tsx b/apps/website/components/feed/ActivityFeed.tsx
similarity index 89%
rename from apps/website/ui/ActivityFeed.tsx
rename to apps/website/components/feed/ActivityFeed.tsx
index 9a48e8fb5..9c33cb0ff 100644
--- a/apps/website/ui/ActivityFeed.tsx
+++ b/apps/website/components/feed/ActivityFeed.tsx
@@ -4,8 +4,8 @@ import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { ActivityItem } from '@/ui/ActivityItem';
import { Icon } from '@/ui/Icon';
-import { ActivityFeedList } from '@/ui/ActivityFeedList';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { ActivityFeedList } from '@/components/feed/ActivityFeedList';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
interface FeedItem {
id: string;
diff --git a/apps/website/ui/ActivityFeedItem.tsx b/apps/website/components/feed/ActivityFeedItem.tsx
similarity index 89%
rename from apps/website/ui/ActivityFeedItem.tsx
rename to apps/website/components/feed/ActivityFeedItem.tsx
index 4a0866210..a64b9acf6 100644
--- a/apps/website/ui/ActivityFeedItem.tsx
+++ b/apps/website/components/feed/ActivityFeedItem.tsx
@@ -1,8 +1,9 @@
import { ReactNode } from 'react';
-import { Box } from './Box';
-import { Surface } from './Surface';
+import { Box } from '@/ui/Box';
+import { Surface } from '@/ui/Surface';
+import { Text } from '@/ui/Text';
interface ActivityFeedItemProps {
icon: ReactNode;
diff --git a/apps/website/ui/ActivityFeedList.tsx b/apps/website/components/feed/ActivityFeedList.tsx
similarity index 87%
rename from apps/website/ui/ActivityFeedList.tsx
rename to apps/website/components/feed/ActivityFeedList.tsx
index f2c969919..7e9b7ca9c 100644
--- a/apps/website/ui/ActivityFeedList.tsx
+++ b/apps/website/components/feed/ActivityFeedList.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
-import { Stack } from './Stack';
+import { Stack } from '@/ui/Stack';
interface ActivityFeedListProps {
children: ReactNode;
diff --git a/apps/website/ui/FeedLayout.tsx b/apps/website/components/feed/FeedLayout.tsx
similarity index 87%
rename from apps/website/ui/FeedLayout.tsx
rename to apps/website/components/feed/FeedLayout.tsx
index f960fc166..b1d53e2c3 100644
--- a/apps/website/ui/FeedLayout.tsx
+++ b/apps/website/components/feed/FeedLayout.tsx
@@ -1,7 +1,7 @@
import { Card } from '@/ui/Card';
-import { FeedList } from '@/ui/FeedList';
-import { UpcomingRacesSidebar } from '@/ui/UpcomingRacesSidebar';
-import { LatestResultsSidebar } from '@/ui/LatestResultsSidebar';
+import { FeedList } from '@/components/feed/FeedList';
+import { UpcomingRacesSidebar } from '@/components/races/UpcomingRacesSidebar';
+import { LatestResultsSidebar } from '@/components/races/LatestResultsSidebar';
interface FeedItemData {
id: string;
diff --git a/apps/website/ui/FeedList.tsx b/apps/website/components/feed/FeedList.tsx
similarity index 100%
rename from apps/website/ui/FeedList.tsx
rename to apps/website/components/feed/FeedList.tsx
diff --git a/apps/website/ui/RecentActivity.tsx b/apps/website/components/feed/RecentActivity.tsx
similarity index 100%
rename from apps/website/ui/RecentActivity.tsx
rename to apps/website/components/feed/RecentActivity.tsx
diff --git a/apps/website/ui/AlternatingSection.tsx b/apps/website/components/landing/AlternatingSection.tsx
similarity index 100%
rename from apps/website/ui/AlternatingSection.tsx
rename to apps/website/components/landing/AlternatingSection.tsx
diff --git a/apps/website/ui/BenefitCard.tsx b/apps/website/components/landing/BenefitCard.tsx
similarity index 94%
rename from apps/website/ui/BenefitCard.tsx
rename to apps/website/components/landing/BenefitCard.tsx
index 9fa0982cf..ad0dbf82b 100644
--- a/apps/website/ui/BenefitCard.tsx
+++ b/apps/website/components/landing/BenefitCard.tsx
@@ -3,11 +3,11 @@
import { motion, useReducedMotion } from 'framer-motion';
import { LucideIcon } from 'lucide-react';
import { useEffect, useState } from 'react';
-import { Box } from './Box';
-import { Heading } from './Heading';
-import { Icon } from './Icon';
-import { Surface } from './Surface';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Heading } from '@/ui/Heading';
+import { Icon } from '@/ui/Icon';
+import { Surface } from '@/ui/Surface';
+import { Text } from '@/ui/Text';
interface BenefitCardProps {
icon: LucideIcon;
diff --git a/apps/website/ui/FeatureGrid.tsx b/apps/website/components/landing/FeatureGrid.tsx
similarity index 97%
rename from apps/website/ui/FeatureGrid.tsx
rename to apps/website/components/landing/FeatureGrid.tsx
index baabd1a26..71d69272f 100644
--- a/apps/website/ui/FeatureGrid.tsx
+++ b/apps/website/components/landing/FeatureGrid.tsx
@@ -1,12 +1,12 @@
'use client';
-import { useRef, useState, useEffect } from 'react';
import { Section } from '@/ui/Section';
import { Container } from '@/ui/Container';
import { Heading } from '@/ui/Heading';
-import { MockupStack } from '@/ui/MockupStack';
+import { MockupStack } from '@/components/mockups/MockupStack';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
+import { Stack } from '@/ui/Stack';
import { LeagueHomeMockup } from '@/components/mockups/LeagueHomeMockup';
import { StandingsTableMockup } from '@/components/mockups/StandingsTableMockup';
import { TeamCompetitionMockup } from '@/components/mockups/TeamCompetitionMockup';
diff --git a/apps/website/ui/LandingHero.tsx b/apps/website/components/landing/LandingHero.tsx
similarity index 99%
rename from apps/website/ui/LandingHero.tsx
rename to apps/website/components/landing/LandingHero.tsx
index 305515d27..b9648c8a4 100644
--- a/apps/website/ui/LandingHero.tsx
+++ b/apps/website/components/landing/LandingHero.tsx
@@ -1,5 +1,5 @@
-
+import { useRef } from 'react';
import { useParallax } from '@/hooks/useScrollProgress';
import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
@@ -126,7 +126,7 @@ export function LandingHero() {
);
-}
\ No newline at end of file
+}
diff --git a/apps/website/ui/LandingItems.tsx b/apps/website/components/landing/LandingItems.tsx
similarity index 100%
rename from apps/website/ui/LandingItems.tsx
rename to apps/website/components/landing/LandingItems.tsx
diff --git a/apps/website/ui/HeaderContent.tsx b/apps/website/components/layout/HeaderContent.tsx
similarity index 95%
rename from apps/website/ui/HeaderContent.tsx
rename to apps/website/components/layout/HeaderContent.tsx
index 4ffd86b34..f9b619be1 100644
--- a/apps/website/ui/HeaderContent.tsx
+++ b/apps/website/components/layout/HeaderContent.tsx
@@ -1,7 +1,7 @@
import React from 'react';
import Image from 'next/image';
import Link from 'next/link';
-import { Text } from './Text';
+import { Text } from '@/ui/Text';
export function HeaderContent() {
return (
diff --git a/apps/website/ui/LeaderboardItem.tsx b/apps/website/components/leaderboards/LeaderboardItem.tsx
similarity index 94%
rename from apps/website/ui/LeaderboardItem.tsx
rename to apps/website/components/leaderboards/LeaderboardItem.tsx
index 471ee3de0..3d238f8e0 100644
--- a/apps/website/ui/LeaderboardItem.tsx
+++ b/apps/website/components/leaderboards/LeaderboardItem.tsx
@@ -1,9 +1,9 @@
import React from 'react';
-import Image from 'next/image';
import { Crown, Flag } from 'lucide-react';
-import { Box } from './Box';
-import { Text } from './Text';
-import { Stack } from './Stack';
+import { Box } from '@/ui/Box';
+import { Text } from '@/ui/Text';
+import { Stack } from '@/ui/Stack';
+import { Image } from '@/ui/Image';
import { mediaConfig } from '@/lib/config/mediaConfig';
interface LeaderboardItemProps {
@@ -80,7 +80,7 @@ export function LeaderboardItem({
{/* Avatar */}
-
+
{/* Info */}
diff --git a/apps/website/ui/LeaderboardPreview.tsx b/apps/website/components/leaderboards/LeaderboardPreview.tsx
similarity index 97%
rename from apps/website/ui/LeaderboardPreview.tsx
rename to apps/website/components/leaderboards/LeaderboardPreview.tsx
index 86073f2a9..23cb4dd20 100644
--- a/apps/website/ui/LeaderboardPreview.tsx
+++ b/apps/website/components/leaderboards/LeaderboardPreview.tsx
@@ -5,7 +5,7 @@ import { Box } from '@/ui/Box';
import { Button } from '@/ui/Button';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
-import { LeaderboardItem } from '@/ui/LeaderboardItem';
+import { LeaderboardItem } from '@/components/leaderboards/LeaderboardItem';
import { LeaderboardList } from '@/ui/LeaderboardList';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
diff --git a/apps/website/ui/RankingList.tsx b/apps/website/components/leaderboards/RankingList.tsx
similarity index 86%
rename from apps/website/ui/RankingList.tsx
rename to apps/website/components/leaderboards/RankingList.tsx
index 9e0e05a75..2447130f2 100644
--- a/apps/website/ui/RankingList.tsx
+++ b/apps/website/components/leaderboards/RankingList.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
-import { Stack } from './Stack';
+import { Stack } from '@/ui/Stack';
interface RankingListProps {
children: ReactNode;
diff --git a/apps/website/ui/RankingListItem.tsx b/apps/website/components/leaderboards/RankingListItem.tsx
similarity index 94%
rename from apps/website/ui/RankingListItem.tsx
rename to apps/website/components/leaderboards/RankingListItem.tsx
index 33b0dbdcb..bbf2206aa 100644
--- a/apps/website/ui/RankingListItem.tsx
+++ b/apps/website/components/leaderboards/RankingListItem.tsx
@@ -1,7 +1,7 @@
import React from 'react';
-import { Box } from './Box';
-import { Text } from './Text';
-import { Stack } from './Stack';
+import { Box } from '@/ui/Box';
+import { Text } from '@/ui/Text';
+import { Stack } from '@/ui/Stack';
interface RankingListItemProps {
name: string;
diff --git a/apps/website/ui/ChampionshipStandings.tsx b/apps/website/components/leagues/ChampionshipStandings.tsx
similarity index 94%
rename from apps/website/ui/ChampionshipStandings.tsx
rename to apps/website/components/leagues/ChampionshipStandings.tsx
index 5370d0f86..f6c701923 100644
--- a/apps/website/ui/ChampionshipStandings.tsx
+++ b/apps/website/components/leagues/ChampionshipStandings.tsx
@@ -2,7 +2,7 @@
import { routes } from '@/lib/routing/RouteConfig';
import { Card } from '@/ui/Card';
-import { ChampionshipStandingsList } from '@/ui/ChampionshipStandingsList';
+import { ChampionshipStandingsList } from '@/components/leagues/ChampionshipStandingsList';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
diff --git a/apps/website/ui/ChampionshipStandingsList.tsx b/apps/website/components/leagues/ChampionshipStandingsList.tsx
similarity index 88%
rename from apps/website/ui/ChampionshipStandingsList.tsx
rename to apps/website/components/leagues/ChampionshipStandingsList.tsx
index 8d573d2c5..1d43741a4 100644
--- a/apps/website/ui/ChampionshipStandingsList.tsx
+++ b/apps/website/components/leagues/ChampionshipStandingsList.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
-import { Stack } from './Stack';
+import { Stack } from '@/ui/Stack';
interface ChampionshipStandingsListProps {
children: ReactNode;
diff --git a/apps/website/components/leagues/EmptyState.tsx b/apps/website/components/leagues/EmptyState.tsx
index 768c06dd0..f99b92235 100644
--- a/apps/website/components/leagues/EmptyState.tsx
+++ b/apps/website/components/leagues/EmptyState.tsx
@@ -1,6 +1,6 @@
import { Trophy, Sparkles, LucideIcon } from 'lucide-react';
import { Card } from '@/ui/Card';
-import { EmptyState as UiEmptyState } from '@/ui/EmptyState';
+import { EmptyState as UiEmptyState } from '@/components/shared/state/EmptyState';
interface EmptyStateProps {
title: string;
diff --git a/apps/website/components/leagues/LeagueActivityFeed.tsx b/apps/website/components/leagues/LeagueActivityFeed.tsx
index ceda2beb8..f3d2ecb48 100644
--- a/apps/website/components/leagues/LeagueActivityFeed.tsx
+++ b/apps/website/components/leagues/LeagueActivityFeed.tsx
@@ -1,7 +1,7 @@
import React, { useMemo } from 'react';
import { Calendar, UserPlus, UserMinus, Shield, Flag, AlertTriangle } from 'lucide-react';
import { useLeagueRaces } from "@/hooks/league/useLeagueRaces";
-import { ActivityFeedItem } from '@/ui/ActivityFeedItem';
+import { ActivityFeedItem } from '@/components/feed/ActivityFeedItem';
import { Icon } from '@/ui/Icon';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
diff --git a/apps/website/ui/LeagueCardWrapper.tsx b/apps/website/components/leagues/LeagueCardWrapper.tsx
similarity index 100%
rename from apps/website/ui/LeagueCardWrapper.tsx
rename to apps/website/components/leagues/LeagueCardWrapper.tsx
diff --git a/apps/website/ui/LeagueMemberRow.tsx b/apps/website/components/leagues/LeagueMemberRow.tsx
similarity index 89%
rename from apps/website/ui/LeagueMemberRow.tsx
rename to apps/website/components/leagues/LeagueMemberRow.tsx
index c2774abea..81e7189a6 100644
--- a/apps/website/ui/LeagueMemberRow.tsx
+++ b/apps/website/components/leagues/LeagueMemberRow.tsx
@@ -1,9 +1,9 @@
import React, { ReactNode } from 'react';
-import { TableRow, TableCell } from './Table';
-import { Box } from './Box';
-import { Text } from './Text';
-import { Badge } from './Badge';
-import { DriverIdentity } from './DriverIdentity';
+import { TableRow, TableCell } from '@/ui/Table';
+import { Box } from '@/ui/Box';
+import { Text } from '@/ui/Text';
+import { Badge } from '@/ui/Badge';
+import { DriverIdentity } from '@/components/drivers/DriverIdentity';
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
interface LeagueMemberRowProps {
@@ -92,7 +92,7 @@ export function LeagueMemberRow({
{actions && (
-
+
{actions}
)}
diff --git a/apps/website/components/leagues/LeagueMembers.tsx b/apps/website/components/leagues/LeagueMembers.tsx
index 97dda4679..956763ad5 100644
--- a/apps/website/components/leagues/LeagueMembers.tsx
+++ b/apps/website/components/leagues/LeagueMembers.tsx
@@ -13,8 +13,8 @@ import { Text } from '@/ui/Text';
import { Select } from '@/ui/Select';
import { Button } from '@/ui/Button';
import { LeagueMemberTable } from '@/ui/LeagueMemberTable';
-import { LeagueMemberRow } from '@/ui/LeagueMemberRow';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { LeagueMemberRow } from '@/components/leagues/LeagueMemberRow';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
interface LeagueMembersProps {
leagueId: string;
diff --git a/apps/website/components/leagues/LeagueOwnershipTransfer.tsx b/apps/website/components/leagues/LeagueOwnershipTransfer.tsx
index 7963c5375..f86ce5a8e 100644
--- a/apps/website/components/leagues/LeagueOwnershipTransfer.tsx
+++ b/apps/website/components/leagues/LeagueOwnershipTransfer.tsx
@@ -1,5 +1,5 @@
import React, { useState } from 'react';
-import { DriverSummaryPill } from '@/ui/DriverSummaryPillWrapper';
+import { DriverSummaryPill } from '@/components/drivers/DriverSummaryPillWrapper';
import { Button } from '@/ui/Button';
import { UserCog } from 'lucide-react';
import { LeagueSettingsViewModel } from '@/lib/view-models/LeagueSettingsViewModel';
diff --git a/apps/website/components/leagues/LeagueSchedule.tsx b/apps/website/components/leagues/LeagueSchedule.tsx
index b812c8819..d3bd3fdbb 100644
--- a/apps/website/components/leagues/LeagueSchedule.tsx
+++ b/apps/website/components/leagues/LeagueSchedule.tsx
@@ -7,7 +7,7 @@ import { useState } from 'react';
import type { LeagueScheduleRaceViewModel } from '@/lib/view-models/LeagueScheduleViewModel';
// Shared state components
-import { StateContainer } from '@/ui/StateContainer';
+import { StateContainer } from '@/components/shared/state/StateContainer';
import { useLeagueSchedule } from "@/hooks/league/useLeagueSchedule";
import { Calendar } from 'lucide-react';
import { Box } from '@/ui/Box';
diff --git a/apps/website/ui/LeagueSummaryCardWrapper.tsx b/apps/website/components/leagues/LeagueSummaryCardWrapper.tsx
similarity index 100%
rename from apps/website/ui/LeagueSummaryCardWrapper.tsx
rename to apps/website/components/leagues/LeagueSummaryCardWrapper.tsx
diff --git a/apps/website/components/leagues/LeagueTimingsSection.tsx b/apps/website/components/leagues/LeagueTimingsSection.tsx
index 39927b027..c919b5263 100644
--- a/apps/website/components/leagues/LeagueTimingsSection.tsx
+++ b/apps/website/components/leagues/LeagueTimingsSection.tsx
@@ -21,7 +21,7 @@ import {
import type { LeagueConfigFormModel } from '@/lib/types/LeagueConfigFormModel';
import type { Weekday } from '@/lib/types/Weekday';
import { Input } from '@/ui/Input';
-import RangeField from '@/ui/RangeField';
+import { RangeField } from '@/components/shared/RangeField';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
diff --git a/apps/website/ui/PendingProtestsList.tsx b/apps/website/components/leagues/PendingProtestsList.tsx
similarity index 72%
rename from apps/website/ui/PendingProtestsList.tsx
rename to apps/website/components/leagues/PendingProtestsList.tsx
index 85af91f30..d4607b8e2 100644
--- a/apps/website/ui/PendingProtestsList.tsx
+++ b/apps/website/components/leagues/PendingProtestsList.tsx
@@ -5,7 +5,7 @@ import { ProtestViewModel } from "@/lib/view-models/ProtestViewModel";
import { RaceViewModel } from "@/lib/view-models/RaceViewModel";
import { Box } from "@/ui/Box";
import { Card } from "@/ui/Card";
-import { ProtestListItem } from "@/ui/ProtestListItem";
+import { ProtestListItem } from "./ProtestListItem";
import { Stack } from "@/ui/Stack";
import { Text } from "@/ui/Text";
import { Flag } from "lucide-react";
@@ -21,7 +21,9 @@ interface PendingProtestsListProps {
export function PendingProtestsList({
protests,
+ drivers,
leagueId,
+ onReviewProtest,
}: PendingProtestsListProps) {
if (protests.length === 0) {
@@ -49,17 +51,25 @@ export function PendingProtestsList({
const daysSinceFiled = Math.floor((Date.now() - new Date(filedAt).getTime()) / (1000 * 60 * 60 * 24));
const isUrgent = daysSinceFiled > 2;
+ const protester = drivers[protest.protestingDriverId];
+ const accused = drivers[protest.accusedDriverId];
+
return (
onReviewProtest(protest)}
/>
);
})}
diff --git a/apps/website/ui/ProtestCardWrapper.tsx b/apps/website/components/leagues/ProtestCardWrapper.tsx
similarity index 96%
rename from apps/website/ui/ProtestCardWrapper.tsx
rename to apps/website/components/leagues/ProtestCardWrapper.tsx
index 1728cb965..17f7e694a 100644
--- a/apps/website/ui/ProtestCardWrapper.tsx
+++ b/apps/website/components/leagues/ProtestCardWrapper.tsx
@@ -1,7 +1,7 @@
import { routes } from '@/lib/routing/RouteConfig';
-import { ProtestListItem } from '@/ui/ProtestListItem';
+import { ProtestListItem } from './ProtestListItem';
interface Protest {
id: string;
diff --git a/apps/website/ui/ProtestListItem.tsx b/apps/website/components/leagues/ProtestListItem.tsx
similarity index 92%
rename from apps/website/ui/ProtestListItem.tsx
rename to apps/website/components/leagues/ProtestListItem.tsx
index c84ba69be..588ea2f66 100644
--- a/apps/website/ui/ProtestListItem.tsx
+++ b/apps/website/components/leagues/ProtestListItem.tsx
@@ -1,14 +1,14 @@
import { AlertCircle, AlertTriangle, Video } from 'lucide-react';
-import { Badge } from './Badge';
-import { Box } from './Box';
-import { Button } from './Button';
-import { Card } from './Card';
-import { Icon } from './Icon';
-import { Link } from './Link';
-import { Stack } from './Stack';
-import { Text } from './Text';
+import { Badge } from '@/ui/Badge';
+import { Box } from '@/ui/Box';
+import { Button } from '@/ui/Button';
+import { Card } from '@/ui/Card';
+import { Icon } from '@/ui/Icon';
+import { Link } from '@/ui/Link';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
interface ProtestListItemProps {
protesterName: string;
diff --git a/apps/website/ui/MockupStack.tsx b/apps/website/components/mockups/MockupStack.tsx
similarity index 98%
rename from apps/website/ui/MockupStack.tsx
rename to apps/website/components/mockups/MockupStack.tsx
index 1c90ed1b5..7870897b5 100644
--- a/apps/website/ui/MockupStack.tsx
+++ b/apps/website/components/mockups/MockupStack.tsx
@@ -8,7 +8,7 @@ interface MockupStackProps {
index?: number;
}
-export default function MockupStack({ children, index = 0 }: MockupStackProps) {
+export function MockupStack({ children, index = 0 }: MockupStackProps) {
const shouldReduceMotion = useReducedMotion();
const [isMounted, setIsMounted] = useState(false);
const [isMobile, setIsMobile] = useState(true); // Default to mobile (no animations)
diff --git a/apps/website/ui/WorkflowMockup.tsx b/apps/website/components/mockups/WorkflowMockup.tsx
similarity index 97%
rename from apps/website/ui/WorkflowMockup.tsx
rename to apps/website/components/mockups/WorkflowMockup.tsx
index a101ebbc9..7224af897 100644
--- a/apps/website/ui/WorkflowMockup.tsx
+++ b/apps/website/components/mockups/WorkflowMockup.tsx
@@ -3,11 +3,11 @@
import { AnimatePresence, motion, useReducedMotion } from 'framer-motion';
import { CheckCircle2, LucideIcon } from 'lucide-react';
import { useEffect, useState } from 'react';
-import { Box } from './Box';
-import { Icon } from './Icon';
-import { Stack } from './Stack';
-import { Surface } from './Surface';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Icon } from '@/ui/Icon';
+import { Stack } from '@/ui/Stack';
+import { Surface } from '@/ui/Surface';
+import { Text } from '@/ui/Text';
export interface WorkflowStep {
id: number;
diff --git a/apps/website/components/onboarding/PersonalInfoStep.tsx b/apps/website/components/onboarding/PersonalInfoStep.tsx
index 42a8e4468..80b9ebb2d 100644
--- a/apps/website/components/onboarding/PersonalInfoStep.tsx
+++ b/apps/website/components/onboarding/PersonalInfoStep.tsx
@@ -1,7 +1,7 @@
import { User, Clock, ChevronRight } from 'lucide-react';
import { Input } from '@/ui/Input';
import { Heading } from '@/ui/Heading';
-import { CountrySelect } from '@/ui/CountrySelect';
+import { CountrySelect } from '@/components/shared/CountrySelect';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
diff --git a/apps/website/ui/LatestResultsSidebar.tsx b/apps/website/components/races/LatestResultsSidebar.tsx
similarity index 100%
rename from apps/website/ui/LatestResultsSidebar.tsx
rename to apps/website/components/races/LatestResultsSidebar.tsx
diff --git a/apps/website/ui/LiveRacesBanner.tsx b/apps/website/components/races/LiveRacesBanner.tsx
similarity index 100%
rename from apps/website/ui/LiveRacesBanner.tsx
rename to apps/website/components/races/LiveRacesBanner.tsx
diff --git a/apps/website/ui/NextRaceCardWrapper.tsx b/apps/website/components/races/NextRaceCardWrapper.tsx
similarity index 100%
rename from apps/website/ui/NextRaceCardWrapper.tsx
rename to apps/website/components/races/NextRaceCardWrapper.tsx
diff --git a/apps/website/ui/RaceCardWrapper.tsx b/apps/website/components/races/RaceCardWrapper.tsx
similarity index 100%
rename from apps/website/ui/RaceCardWrapper.tsx
rename to apps/website/components/races/RaceCardWrapper.tsx
diff --git a/apps/website/ui/RaceEntryList.tsx b/apps/website/components/races/RaceEntryList.tsx
similarity index 96%
rename from apps/website/ui/RaceEntryList.tsx
rename to apps/website/components/races/RaceEntryList.tsx
index 2578429dd..73bed58d4 100644
--- a/apps/website/ui/RaceEntryList.tsx
+++ b/apps/website/components/races/RaceEntryList.tsx
@@ -1,7 +1,7 @@
import { Card } from '@/ui/Card';
-import { DriverEntryRow } from '@/ui/DriverEntryRow';
+import { DriverEntryRow } from '@/components/drivers/DriverEntryRow';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack';
diff --git a/apps/website/ui/RaceFilterBar.tsx b/apps/website/components/races/RaceFilterBar.tsx
similarity index 100%
rename from apps/website/ui/RaceFilterBar.tsx
rename to apps/website/components/races/RaceFilterBar.tsx
diff --git a/apps/website/ui/RaceList.tsx b/apps/website/components/races/RaceList.tsx
similarity index 97%
rename from apps/website/ui/RaceList.tsx
rename to apps/website/components/races/RaceList.tsx
index d7e55ebe6..8d6b04d22 100644
--- a/apps/website/ui/RaceList.tsx
+++ b/apps/website/components/races/RaceList.tsx
@@ -6,7 +6,7 @@ import { Box } from '@/ui/Box';
import { Card } from '@/ui/Card';
import { DateHeader } from '@/ui/DateHeader';
import { Icon } from '@/ui/Icon';
-import { RaceListItem } from '@/ui/RaceListItem';
+import { RaceListItem } from '@/components/races/RaceListItem';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Calendar, CheckCircle2, Clock, PlayCircle, XCircle } from 'lucide-react';
diff --git a/apps/website/ui/RaceListItem.tsx b/apps/website/components/races/RaceListItem.tsx
similarity index 94%
rename from apps/website/ui/RaceListItem.tsx
rename to apps/website/components/races/RaceListItem.tsx
index 104448c78..2479c83f5 100644
--- a/apps/website/ui/RaceListItem.tsx
+++ b/apps/website/components/races/RaceListItem.tsx
@@ -1,13 +1,13 @@
import { ArrowRight, Car, ChevronRight, LucideIcon, Trophy, Zap } from 'lucide-react';
-import { Badge } from './Badge';
-import { Box } from './Box';
-import { Heading } from './Heading';
-import { Icon } from './Icon';
-import { Link } from './Link';
-import { Stack } from './Stack';
-import { Text } from './Text';
+import { Badge } from '@/ui/Badge';
+import { Box } from '@/ui/Box';
+import { Heading } from '@/ui/Heading';
+import { Icon } from '@/ui/Icon';
+import { Link } from '@/ui/Link';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
interface RaceListItemProps {
track: string;
diff --git a/apps/website/ui/RaceListItemWrapper.tsx b/apps/website/components/races/RaceListItemWrapper.tsx
similarity index 95%
rename from apps/website/ui/RaceListItemWrapper.tsx
rename to apps/website/components/races/RaceListItemWrapper.tsx
index 82f04e3a9..569d8f92b 100644
--- a/apps/website/ui/RaceListItemWrapper.tsx
+++ b/apps/website/components/races/RaceListItemWrapper.tsx
@@ -1,7 +1,7 @@
import { routes } from '@/lib/routing/RouteConfig';
-import { RaceListItem as UiRaceListItem } from '@/ui/RaceListItem';
+import { RaceListItem as UiRaceListItem } from '@/components/races/RaceListItem';
import { CheckCircle2, Clock, PlayCircle, XCircle } from 'lucide-react';
interface Race {
diff --git a/apps/website/ui/RaceResultCardWrapper.tsx b/apps/website/components/races/RaceResultCardWrapper.tsx
similarity index 100%
rename from apps/website/ui/RaceResultCardWrapper.tsx
rename to apps/website/components/races/RaceResultCardWrapper.tsx
diff --git a/apps/website/ui/RaceResultRow.tsx b/apps/website/components/races/RaceResultRow.tsx
similarity index 94%
rename from apps/website/ui/RaceResultRow.tsx
rename to apps/website/components/races/RaceResultRow.tsx
index edde4c2dd..1eb42866d 100644
--- a/apps/website/ui/RaceResultRow.tsx
+++ b/apps/website/components/races/RaceResultRow.tsx
@@ -1,11 +1,11 @@
import { CountryFlagDisplay } from '@/lib/display-objects/CountryFlagDisplay';
-import { Box } from './Box';
-import { Image } from './Image';
-import { Stack } from './Stack';
-import { Surface } from './Surface';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Image } from '@/ui/Image';
+import { Stack } from '@/ui/Stack';
+import { Surface } from '@/ui/Surface';
+import { Text } from '@/ui/Text';
interface ResultEntry {
position: number;
@@ -64,7 +64,7 @@ export function RaceResultRow({ result, points }: RaceResultRowProps) {
{/* Avatar */}
-
+
{CountryFlagDisplay.fromCountryCode(country).toString()}
diff --git a/apps/website/ui/RaceSidebar.tsx b/apps/website/components/races/RaceSidebar.tsx
similarity index 100%
rename from apps/website/ui/RaceSidebar.tsx
rename to apps/website/components/races/RaceSidebar.tsx
diff --git a/apps/website/ui/UpcomingRaces.tsx b/apps/website/components/races/UpcomingRaces.tsx
similarity index 91%
rename from apps/website/ui/UpcomingRaces.tsx
rename to apps/website/components/races/UpcomingRaces.tsx
index 745ea07d6..e0d32ecc2 100644
--- a/apps/website/ui/UpcomingRaces.tsx
+++ b/apps/website/components/races/UpcomingRaces.tsx
@@ -2,14 +2,14 @@
import { routes } from '@/lib/routing/RouteConfig';
import { Card } from '@/ui/Card';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { UpcomingRaceItem } from '@/ui/UpcomingRaceItem';
-import { UpcomingRacesList } from '@/ui/UpcomingRacesList';
+import { UpcomingRacesList } from '@/components/races/UpcomingRacesList';
import { Calendar } from 'lucide-react';
interface UpcomingRace {
diff --git a/apps/website/ui/UpcomingRacesList.tsx b/apps/website/components/races/UpcomingRacesList.tsx
similarity index 87%
rename from apps/website/ui/UpcomingRacesList.tsx
rename to apps/website/components/races/UpcomingRacesList.tsx
index c4c871f09..7c5d4af99 100644
--- a/apps/website/ui/UpcomingRacesList.tsx
+++ b/apps/website/components/races/UpcomingRacesList.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode } from 'react';
-import { Stack } from './Stack';
+import { Stack } from '@/ui/Stack';
interface UpcomingRacesListProps {
children: ReactNode;
diff --git a/apps/website/ui/UpcomingRacesSidebar.tsx b/apps/website/components/races/UpcomingRacesSidebar.tsx
similarity index 100%
rename from apps/website/ui/UpcomingRacesSidebar.tsx
rename to apps/website/components/races/UpcomingRacesSidebar.tsx
diff --git a/apps/website/ui/CountrySelect.tsx b/apps/website/components/shared/CountrySelect.tsx
similarity index 99%
rename from apps/website/ui/CountrySelect.tsx
rename to apps/website/components/shared/CountrySelect.tsx
index 47c1d5590..d7d6d8cb2 100644
--- a/apps/website/ui/CountrySelect.tsx
+++ b/apps/website/components/shared/CountrySelect.tsx
@@ -2,7 +2,7 @@
import { Check, ChevronDown, Globe, Search } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';
-import { CountryFlag } from './CountryFlag';
+import { CountryFlag } from '@/ui/CountryFlag';
export interface Country {
code: string;
diff --git a/apps/website/ui/RangeField.tsx b/apps/website/components/shared/RangeField.tsx
similarity index 99%
rename from apps/website/ui/RangeField.tsx
rename to apps/website/components/shared/RangeField.tsx
index 3dfd8eda4..1c173574e 100644
--- a/apps/website/ui/RangeField.tsx
+++ b/apps/website/components/shared/RangeField.tsx
@@ -20,7 +20,7 @@ interface RangeFieldProps {
compact?: boolean;
}
-export default function RangeField({
+export function RangeField({
label,
value,
min,
diff --git a/apps/website/ui/EmptyState.tsx b/apps/website/components/shared/state/EmptyState.tsx
similarity index 99%
rename from apps/website/ui/EmptyState.tsx
rename to apps/website/components/shared/state/EmptyState.tsx
index 3e0b6b3da..f3a9af12d 100644
--- a/apps/website/ui/EmptyState.tsx
+++ b/apps/website/components/shared/state/EmptyState.tsx
@@ -1,7 +1,7 @@
-import { Button } from './Button';
-import { EmptyStateProps } from './state-types';
+import { Button } from '@/ui/Button';
+import { EmptyStateProps } from '@/ui/state-types';
// Illustration components (simple SVG representations)
const Illustrations = {
diff --git a/apps/website/ui/ErrorDisplay.tsx b/apps/website/components/shared/state/ErrorDisplay.tsx
similarity index 95%
rename from apps/website/ui/ErrorDisplay.tsx
rename to apps/website/components/shared/state/ErrorDisplay.tsx
index 0b320cbea..a58cbe260 100644
--- a/apps/website/ui/ErrorDisplay.tsx
+++ b/apps/website/components/shared/state/ErrorDisplay.tsx
@@ -2,14 +2,14 @@
import { ApiError } from '@/lib/api/base/ApiError';
import { AlertCircle, ArrowLeft, Home, RefreshCw } from 'lucide-react';
-import { Box } from './Box';
-import { Button } from './Button';
-import { Heading } from './Heading';
-import { Icon } from './Icon';
-import { Stack } from './Stack';
-import { ErrorDisplayAction, ErrorDisplayProps } from './state-types';
-import { Surface } from './Surface';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Button } from '@/ui/Button';
+import { Heading } from '@/ui/Heading';
+import { Icon } from '@/ui/Icon';
+import { Stack } from '@/ui/Stack';
+import { ErrorDisplayAction, ErrorDisplayProps } from '@/ui/state-types';
+import { Surface } from '@/ui/Surface';
+import { Text } from '@/ui/Text';
export function ErrorDisplay({
error,
diff --git a/apps/website/ui/LoadingWrapper.tsx b/apps/website/components/shared/state/LoadingWrapper.tsx
similarity index 97%
rename from apps/website/ui/LoadingWrapper.tsx
rename to apps/website/components/shared/state/LoadingWrapper.tsx
index e770b87c9..b2738cf41 100644
--- a/apps/website/ui/LoadingWrapper.tsx
+++ b/apps/website/components/shared/state/LoadingWrapper.tsx
@@ -1,9 +1,9 @@
-import { Box } from './Box';
-import { Stack } from './Stack';
-import { LoadingWrapperProps } from './state-types';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Stack } from '@/ui/Stack';
+import { LoadingWrapperProps } from '@/ui/state-types';
+import { Text } from '@/ui/Text';
/**
* LoadingWrapper Component
diff --git a/apps/website/ui/PageWrapper.tsx b/apps/website/components/shared/state/PageWrapper.tsx
similarity index 96%
rename from apps/website/ui/PageWrapper.tsx
rename to apps/website/components/shared/state/PageWrapper.tsx
index f812f9cc5..5ff872e3f 100644
--- a/apps/website/ui/PageWrapper.tsx
+++ b/apps/website/components/shared/state/PageWrapper.tsx
@@ -1,8 +1,8 @@
import React, { ReactNode } from 'react';
import { ApiError } from '@/lib/api/base/ApiError';
-import { LoadingWrapper } from '@/ui/LoadingWrapper';
-import { ErrorDisplay } from '@/ui/ErrorDisplay';
-import { EmptyState } from '@/ui/EmptyState';
+import { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';
+import { ErrorDisplay } from '@/components/shared/state/ErrorDisplay';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import { Box } from '@/ui/Box';
import { Inbox, List, LucideIcon } from 'lucide-react';
diff --git a/apps/website/ui/StateContainer.tsx b/apps/website/components/shared/state/StateContainer.tsx
similarity index 96%
rename from apps/website/ui/StateContainer.tsx
rename to apps/website/components/shared/state/StateContainer.tsx
index 58d606d31..2c72dfb08 100644
--- a/apps/website/ui/StateContainer.tsx
+++ b/apps/website/components/shared/state/StateContainer.tsx
@@ -2,9 +2,9 @@
import React from 'react';
import { StateContainerProps, StateContainerConfig } from '@/ui/state-types';
-import { LoadingWrapper } from '@/ui/LoadingWrapper';
-import { ErrorDisplay } from '@/ui/ErrorDisplay';
-import { EmptyState } from '@/ui/EmptyState';
+import { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';
+import { ErrorDisplay } from '@/components/shared/state/ErrorDisplay';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import { Box } from '@/ui/Box';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
@@ -159,6 +159,11 @@ export function StateContainer({
);
}
+ // Custom success render
+ if (config?.customRender?.success) {
+ return <>{config.customRender.success(data as T)}>;
+ }
+
// At this point, data is guaranteed to be non-null and non-undefined
return <>{children(data as T)}>;
}
@@ -383,4 +388,4 @@ export function GridStateContainer({
{children}
);
-}
\ No newline at end of file
+}
diff --git a/apps/website/ui/StatefulPageWrapper.tsx b/apps/website/components/shared/state/StatefulPageWrapper.tsx
similarity index 87%
rename from apps/website/ui/StatefulPageWrapper.tsx
rename to apps/website/components/shared/state/StatefulPageWrapper.tsx
index 38fb019cd..ad62a66c0 100644
--- a/apps/website/ui/StatefulPageWrapper.tsx
+++ b/apps/website/components/shared/state/StatefulPageWrapper.tsx
@@ -1,7 +1,7 @@
'use client';
import React from 'react';
-import { PageWrapper, PageWrapperProps } from './PageWrapper';
+import { PageWrapper, PageWrapperProps } from '@/components/shared/state/PageWrapper';
/**
* Stateful Page Wrapper - CLIENT SIDE ONLY
@@ -56,4 +56,4 @@ export function StatefulPageWrapper({
}
// Re-export types for convenience
-export type { PageWrapperProps, PageWrapperLoadingConfig, PageWrapperErrorConfig, PageWrapperEmptyConfig } from './PageWrapper';
\ No newline at end of file
+export type { PageWrapperProps, PageWrapperLoadingConfig, PageWrapperErrorConfig, PageWrapperEmptyConfig } from '@/components/shared/state/PageWrapper';
\ No newline at end of file
diff --git a/apps/website/ui/FriendsPreview.tsx b/apps/website/components/social/FriendsPreview.tsx
similarity index 100%
rename from apps/website/ui/FriendsPreview.tsx
rename to apps/website/components/social/FriendsPreview.tsx
diff --git a/apps/website/ui/FriendsSidebar.tsx b/apps/website/components/social/FriendsSidebar.tsx
similarity index 96%
rename from apps/website/ui/FriendsSidebar.tsx
rename to apps/website/components/social/FriendsSidebar.tsx
index 82c7c7148..36a9c9e28 100644
--- a/apps/website/ui/FriendsSidebar.tsx
+++ b/apps/website/components/social/FriendsSidebar.tsx
@@ -3,7 +3,7 @@
import { routes } from '@/lib/routing/RouteConfig';
import { Box } from '@/ui/Box';
import { Card } from '@/ui/Card';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
import { FriendItem } from '@/ui/FriendItem';
import { FriendsList } from '@/ui/FriendsList';
import { Heading } from '@/ui/Heading';
diff --git a/apps/website/components/sponsors/SponsorBenefitCard.tsx b/apps/website/components/sponsors/SponsorBenefitCard.tsx
index 7eda95e05..6794e126b 100644
--- a/apps/website/components/sponsors/SponsorBenefitCard.tsx
+++ b/apps/website/components/sponsors/SponsorBenefitCard.tsx
@@ -2,7 +2,7 @@
import React from 'react';
import { LucideIcon } from 'lucide-react';
-import { BenefitCard } from '@/ui/BenefitCard';
+import { BenefitCard } from '@/components/landing/BenefitCard';
interface SponsorBenefitCardProps {
icon: LucideIcon;
diff --git a/apps/website/ui/SponsorHero.tsx b/apps/website/components/sponsors/SponsorHero.tsx
similarity index 95%
rename from apps/website/ui/SponsorHero.tsx
rename to apps/website/components/sponsors/SponsorHero.tsx
index 09a24d165..44ca46333 100644
--- a/apps/website/ui/SponsorHero.tsx
+++ b/apps/website/components/sponsors/SponsorHero.tsx
@@ -3,11 +3,16 @@
import { motion, useReducedMotion } from 'framer-motion';
import { Building2 } from 'lucide-react';
import { useEffect, useState } from 'react';
-import { Box } from './Box';
-import { Heading } from './Heading';
-import { Icon } from './Icon';
-import { Text } from './Text';
+import { Box } from '@/ui/Box';
+import { Heading } from '@/ui/Heading';
+import { Icon } from '@/ui/Icon';
+import { Text } from '@/ui/Text';
+interface SponsorHeroProps {
+ title: string;
+ subtitle: string;
+ children?: React.ReactNode;
+}
export function SponsorHero({ title, subtitle, children }: SponsorHeroProps) {
const shouldReduceMotion = useReducedMotion();
diff --git a/apps/website/components/sponsors/SponsorWorkflowMockup.tsx b/apps/website/components/sponsors/SponsorWorkflowMockup.tsx
index 8e75ea978..cf0dca3f0 100644
--- a/apps/website/components/sponsors/SponsorWorkflowMockup.tsx
+++ b/apps/website/components/sponsors/SponsorWorkflowMockup.tsx
@@ -8,7 +8,7 @@ import {
Car,
TrendingUp,
} from 'lucide-react';
-import { WorkflowMockup, WorkflowStep } from '@/ui/WorkflowMockup';
+import { WorkflowMockup, WorkflowStep } from '@/components/mockups/WorkflowMockup';
const WORKFLOW_STEPS: WorkflowStep[] = [
{
diff --git a/apps/website/components/teams/TeamAdmin.tsx b/apps/website/components/teams/TeamAdmin.tsx
index f0765413d..e3ff51a3c 100644
--- a/apps/website/components/teams/TeamAdmin.tsx
+++ b/apps/website/components/teams/TeamAdmin.tsx
@@ -12,7 +12,7 @@ import { Heading } from '@/ui/Heading';
import { JoinRequestList } from '@/ui/JoinRequestList';
import { JoinRequestItem } from '@/ui/JoinRequestItem';
import { DangerZone } from '@/ui/DangerZone';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
import { useTeamJoinRequests, useUpdateTeam, useApproveJoinRequest, useRejectJoinRequest } from "@/hooks/team";
import type { TeamJoinRequestViewModel } from '@/lib/view-models/TeamJoinRequestViewModel';
diff --git a/apps/website/ui/TeamHero.tsx b/apps/website/components/teams/TeamHero.tsx
similarity index 100%
rename from apps/website/ui/TeamHero.tsx
rename to apps/website/components/teams/TeamHero.tsx
diff --git a/apps/website/ui/TeamHeroSection.tsx b/apps/website/components/teams/TeamHeroSection.tsx
similarity index 92%
rename from apps/website/ui/TeamHeroSection.tsx
rename to apps/website/components/teams/TeamHeroSection.tsx
index da8c8c12e..4715a7a72 100644
--- a/apps/website/ui/TeamHeroSection.tsx
+++ b/apps/website/components/teams/TeamHeroSection.tsx
@@ -2,11 +2,11 @@
import { Users } from 'lucide-react';
import { ReactNode } from 'react';
-import { Badge } from './Badge';
-import { Box } from './Box';
-import { Heading } from './Heading';
-import { Stack } from './Stack';
-import { Text } from './Text';
+import { Badge } from '@/ui/Badge';
+import { Box } from '@/ui/Box';
+import { Heading } from '@/ui/Heading';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
interface TeamHeroSectionProps {
title: ReactNode;
diff --git a/apps/website/ui/TeamHeroSectionWrapper.tsx b/apps/website/components/teams/TeamHeroSectionWrapper.tsx
similarity index 95%
rename from apps/website/ui/TeamHeroSectionWrapper.tsx
rename to apps/website/components/teams/TeamHeroSectionWrapper.tsx
index 99417ec56..2329897dd 100644
--- a/apps/website/ui/TeamHeroSectionWrapper.tsx
+++ b/apps/website/components/teams/TeamHeroSectionWrapper.tsx
@@ -5,8 +5,8 @@ import { Button } from '@/ui/Button';
import { Icon } from '@/ui/Icon';
import { SkillLevelButton } from '@/ui/SkillLevelButton';
import { Stack } from '@/ui/Stack';
-import { TeamHeroSection as UiTeamHeroSection } from '@/ui/TeamHeroSection';
-import { TeamHeroStats } from '@/ui/TeamHeroStats';
+import { TeamHeroSection as UiTeamHeroSection } from '@/components/teams/TeamHeroSection';
+import { TeamHeroStats } from '@/components/teams/TeamHeroStats';
import { Text } from '@/ui/Text';
import {
Crown,
diff --git a/apps/website/ui/TeamHeroStats.tsx b/apps/website/components/teams/TeamHeroStats.tsx
similarity index 90%
rename from apps/website/ui/TeamHeroStats.tsx
rename to apps/website/components/teams/TeamHeroStats.tsx
index ea4aabfbb..16217d3e5 100644
--- a/apps/website/ui/TeamHeroStats.tsx
+++ b/apps/website/components/teams/TeamHeroStats.tsx
@@ -1,9 +1,9 @@
import React from 'react';
import { Users, UserPlus } from 'lucide-react';
-import { Box } from './Box';
-import { Text } from './Text';
-import { Icon } from './Icon';
-import { Stack } from './Stack';
+import { Box } from '@/ui/Box';
+import { Text } from '@/ui/Text';
+import { Icon } from '@/ui/Icon';
+import { Stack } from '@/ui/Stack';
interface TeamHeroStatsProps {
teamCount: number;
diff --git a/apps/website/ui/TeamIdentity.tsx b/apps/website/components/teams/TeamIdentity.tsx
similarity index 85%
rename from apps/website/ui/TeamIdentity.tsx
rename to apps/website/components/teams/TeamIdentity.tsx
index 7ccb709e2..26e24efd1 100644
--- a/apps/website/ui/TeamIdentity.tsx
+++ b/apps/website/components/teams/TeamIdentity.tsx
@@ -1,8 +1,8 @@
import React from 'react';
-import { Box } from './Box';
-import { Stack } from './Stack';
-import { Text } from './Text';
-import { Image } from './Image';
+import { Box } from '@/ui/Box';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
+import { Image } from '@/ui/Image';
interface TeamIdentityProps {
name: string;
@@ -20,6 +20,9 @@ export function TeamIdentity({ name, logoUrl, performanceLevel, category }: Team
alt={name}
width={40}
height={40}
+ fullWidth
+ fullHeight
+ objectFit="cover"
/>
diff --git a/apps/website/ui/TeamLeaderboardPreviewWrapper.tsx b/apps/website/components/teams/TeamLeaderboardPreviewWrapper.tsx
similarity index 100%
rename from apps/website/ui/TeamLeaderboardPreviewWrapper.tsx
rename to apps/website/components/teams/TeamLeaderboardPreviewWrapper.tsx
diff --git a/apps/website/ui/TeamPodium.tsx b/apps/website/components/teams/TeamPodium.tsx
similarity index 94%
rename from apps/website/ui/TeamPodium.tsx
rename to apps/website/components/teams/TeamPodium.tsx
index 9435f72ce..8185d5807 100644
--- a/apps/website/ui/TeamPodium.tsx
+++ b/apps/website/components/teams/TeamPodium.tsx
@@ -2,13 +2,13 @@ import React from 'react';
import { Trophy, Crown, Users } from 'lucide-react';
import type { TeamSummaryViewModel } from '@/lib/view-models/TeamSummaryViewModel';
import { getMediaUrl } from '@/lib/utilities/media';
-import { Box } from './Box';
-import { Stack } from './Stack';
-import { Text } from './Text';
-import { Icon } from './Icon';
-import { Button } from './Button';
-import { Image } from './Image';
-import { Podium, PodiumItem } from './Podium';
+import { Box } from '@/ui/Box';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
+import { Icon } from '@/ui/Icon';
+import { Button } from '@/ui/Button';
+import { Image } from '@/ui/Image';
+import { Podium, PodiumItem } from '@/ui/Podium';
interface TeamPodiumProps {
teams: TeamSummaryViewModel[];
diff --git a/apps/website/ui/TeamRankingsTable.tsx b/apps/website/components/teams/TeamRankingsTable.tsx
similarity index 91%
rename from apps/website/ui/TeamRankingsTable.tsx
rename to apps/website/components/teams/TeamRankingsTable.tsx
index 177258b97..fea9f1563 100644
--- a/apps/website/ui/TeamRankingsTable.tsx
+++ b/apps/website/components/teams/TeamRankingsTable.tsx
@@ -1,13 +1,13 @@
import React from 'react';
import { Users } from 'lucide-react';
-import { Box } from './Box';
-import { Stack } from './Stack';
-import { Text } from './Text';
-import { Icon } from './Icon';
-import { Card } from './Card';
-import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from './Table';
-import { RankBadge } from './RankBadge';
-import { TeamIdentity } from './TeamIdentity';
+import { Box } from '@/ui/Box';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
+import { Icon } from '@/ui/Icon';
+import { Card } from '@/ui/Card';
+import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from '@/ui/Table';
+import { RankBadge } from '@/ui/RankBadge';
+import { TeamIdentity } from '@/components/teams/TeamIdentity';
import { getMediaUrl } from '@/lib/utilities/media';
interface Team {
diff --git a/apps/website/components/teams/TeamRoster.tsx b/apps/website/components/teams/TeamRoster.tsx
index f70647ae1..8e108e9bb 100644
--- a/apps/website/components/teams/TeamRoster.tsx
+++ b/apps/website/components/teams/TeamRoster.tsx
@@ -12,8 +12,8 @@ import { Select } from '@/ui/Select';
import { Button } from '@/ui/Button';
import { routes } from '@/lib/routing/RouteConfig';
import { TeamRosterList } from '@/ui/TeamRosterList';
-import { TeamRosterItem } from '@/ui/TeamRosterItem';
-import { MinimalEmptyState } from '@/ui/EmptyState';
+import { TeamRosterItem } from '@/components/teams/TeamRosterItem';
+import { MinimalEmptyState } from '@/components/shared/state/EmptyState';
import { sortMembers } from '@/lib/utilities/roster-utils';
export type TeamRole = 'owner' | 'admin' | 'member';
diff --git a/apps/website/ui/TeamRosterItem.tsx b/apps/website/components/teams/TeamRosterItem.tsx
similarity index 91%
rename from apps/website/ui/TeamRosterItem.tsx
rename to apps/website/components/teams/TeamRosterItem.tsx
index 953626c04..a5b63d5f7 100644
--- a/apps/website/ui/TeamRosterItem.tsx
+++ b/apps/website/components/teams/TeamRosterItem.tsx
@@ -1,8 +1,8 @@
import React, { ReactNode } from 'react';
-import { Box } from './Box';
-import { Stack } from './Stack';
-import { Text } from './Text';
-import { DriverIdentity } from './DriverIdentity';
+import { Box } from '@/ui/Box';
+import { Stack } from '@/ui/Stack';
+import { Text } from '@/ui/Text';
+import { DriverIdentity } from '@/components/drivers/DriverIdentity';
import { DriverViewModel } from '@/lib/view-models/DriverViewModel';
interface TeamRosterItemProps {
diff --git a/apps/website/components/teams/TeamStandings.tsx b/apps/website/components/teams/TeamStandings.tsx
index 24ba6df86..66df5a5dd 100644
--- a/apps/website/components/teams/TeamStandings.tsx
+++ b/apps/website/components/teams/TeamStandings.tsx
@@ -5,8 +5,8 @@ import { useTeamStandings } from "@/hooks/team/useTeamStandings";
import { Box } from '@/ui/Box';
import { Heading } from '@/ui/Heading';
import { StandingsList } from '@/ui/StandingsList';
-import { LoadingWrapper } from '@/ui/LoadingWrapper';
-import { EmptyState } from '@/ui/EmptyState';
+import { LoadingWrapper } from '@/components/shared/state/LoadingWrapper';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import { Trophy } from 'lucide-react';
interface TeamStandingsProps {
diff --git a/apps/website/ui/TopThreePodium.tsx b/apps/website/components/teams/TopThreePodium.tsx
similarity index 100%
rename from apps/website/ui/TopThreePodium.tsx
rename to apps/website/components/teams/TopThreePodium.tsx
diff --git a/apps/website/ui/WhyJoinTeamSection.tsx b/apps/website/components/teams/WhyJoinTeamSection.tsx
similarity index 96%
rename from apps/website/ui/WhyJoinTeamSection.tsx
rename to apps/website/components/teams/WhyJoinTeamSection.tsx
index 3e7125c5b..f18158667 100644
--- a/apps/website/ui/WhyJoinTeamSection.tsx
+++ b/apps/website/components/teams/WhyJoinTeamSection.tsx
@@ -10,7 +10,7 @@ import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
import { Grid } from '@/ui/Grid';
-import { BenefitCard } from '@/ui/BenefitCard';
+import { BenefitCard } from '@/components/landing/BenefitCard';
interface Benefit {
icon: LucideIcon;
diff --git a/apps/website/templates/DashboardTemplate.tsx b/apps/website/templates/DashboardTemplate.tsx
index e6da2ecc5..ed49d2126 100644
--- a/apps/website/templates/DashboardTemplate.tsx
+++ b/apps/website/templates/DashboardTemplate.tsx
@@ -6,12 +6,12 @@ import { Box } from '@/ui/Box';
import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
-import { DashboardHero } from '@/ui/DashboardHeroWrapper';
-import { NextRaceCard } from '@/ui/NextRaceCardWrapper';
-import { ChampionshipStandings } from '@/ui/ChampionshipStandings';
-import { ActivityFeed } from '@/ui/ActivityFeed';
-import { UpcomingRaces } from '@/ui/UpcomingRaces';
-import { FriendsSidebar } from '@/ui/FriendsSidebar';
+import { DashboardHero } from '@/components/dashboard/DashboardHeroWrapper';
+import { NextRaceCard } from '@/components/races/NextRaceCardWrapper';
+import { ChampionshipStandings } from '@/components/leagues/ChampionshipStandings';
+import { ActivityFeed } from '@/components/feed/ActivityFeed';
+import { UpcomingRaces } from '@/components/races/UpcomingRaces';
+import { FriendsSidebar } from '@/components/social/FriendsSidebar';
import { Stack } from '@/ui/Stack';
interface DashboardTemplateProps {
diff --git a/apps/website/templates/DriverProfileTemplate.tsx b/apps/website/templates/DriverProfileTemplate.tsx
index 10ffeeaa9..990d16297 100644
--- a/apps/website/templates/DriverProfileTemplate.tsx
+++ b/apps/website/templates/DriverProfileTemplate.tsx
@@ -2,12 +2,12 @@
import { RatingBreakdown } from '@/ui/RatingBreakdown';
import { Breadcrumbs } from '@/ui/Breadcrumbs';
-import { AchievementGrid } from '@/ui/AchievementGrid';
+import { AchievementGrid } from '@/components/achievements/AchievementGrid';
import { CareerStats } from '@/ui/CareerStats';
-import { FriendsPreview } from '@/ui/FriendsPreview';
+import { FriendsPreview } from '@/components/social/FriendsPreview';
import { PerformanceOverview } from '@/ui/PerformanceOverview';
import { ProfileBio } from '@/ui/ProfileBio';
-import { ProfileHero } from '@/ui/ProfileHero';
+import { ProfileHero } from '@/components/drivers/ProfileHero';
import { ProfileTabs, type ProfileTab } from '@/ui/ProfileTabs';
import { RacingProfile } from '@/ui/RacingProfile';
import { TeamMembershipGrid } from '@/ui/TeamMembershipGrid';
diff --git a/apps/website/templates/DriversTemplate.tsx b/apps/website/templates/DriversTemplate.tsx
index 471bef8fa..8c9aecb73 100644
--- a/apps/website/templates/DriversTemplate.tsx
+++ b/apps/website/templates/DriversTemplate.tsx
@@ -16,14 +16,14 @@ import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
import { Surface } from '@/ui/Surface';
import { Icon } from '@/ui/Icon';
-import { FeaturedDriverCard } from '@/ui/FeaturedDriverCard';
+import { FeaturedDriverCard } from '@/components/drivers/FeaturedDriverCard';
import { SkillDistribution } from '@/ui/SkillDistribution';
import { CategoryDistribution } from '@/ui/CategoryDistribution';
-import { LeaderboardPreview } from '@/ui/LeaderboardPreview';
-import { RecentActivity } from '@/ui/RecentActivity';
+import { LeaderboardPreview } from '@/components/leaderboards/LeaderboardPreview';
+import { RecentActivity } from '@/components/feed/RecentActivity';
import { PageHero } from '@/ui/PageHero';
import { DriversSearch } from '@/ui/DriversSearch';
-import { EmptyState } from '@/ui/EmptyState';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import type { DriversViewData } from '@/lib/types/view-data/DriversViewData';
interface DriversTemplateProps {
diff --git a/apps/website/templates/HomeTemplate.tsx b/apps/website/templates/HomeTemplate.tsx
index 0cc60d83b..32eb82662 100644
--- a/apps/website/templates/HomeTemplate.tsx
+++ b/apps/website/templates/HomeTemplate.tsx
@@ -1,9 +1,9 @@
'use client';
import React from 'react';
-import { LandingHero } from '@/ui/LandingHero';
-import { AlternatingSection } from '@/ui/AlternatingSection';
-import { FeatureGrid } from '@/ui/FeatureGrid';
+import { LandingHero } from '@/components/landing/LandingHero';
+import { AlternatingSection } from '@/components/landing/AlternatingSection';
+import { FeatureGrid } from '@/components/landing/FeatureGrid';
import { DiscordCTA } from '@/ui/DiscordCTA';
import { FAQ } from '@/components/landing/FAQ';
import { Footer } from '@/ui/Footer';
@@ -24,7 +24,7 @@ import { Grid } from '@/ui/Grid';
import { Surface } from '@/ui/Surface';
import { getMediaUrl } from '@/lib/utilities/media';
import { routes } from '@/lib/routing/RouteConfig';
-import { FeatureItem, ResultItem, StepItem } from '@/ui/LandingItems';
+import { FeatureItem, ResultItem, StepItem } from '@/components/landing/LandingItems';
import { ModeGuard } from '@/components/shared/ModeGuard';
export interface HomeViewData {
diff --git a/apps/website/templates/LeaderboardsTemplate.tsx b/apps/website/templates/LeaderboardsTemplate.tsx
index 87f914a27..cddcd0c1f 100644
--- a/apps/website/templates/LeaderboardsTemplate.tsx
+++ b/apps/website/templates/LeaderboardsTemplate.tsx
@@ -6,7 +6,7 @@ import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
import { DriverLeaderboardPreview } from '@/components/leaderboards/DriverLeaderboardPreview';
-import { TeamLeaderboardPreview } from '@/ui/TeamLeaderboardPreviewWrapper';
+import { TeamLeaderboardPreview } from '@/components/teams/TeamLeaderboardPreviewWrapper';
import { LeaderboardsHero } from '@/components/leaderboards/LeaderboardsHero';
import type { LeaderboardsViewData } from '@/lib/view-data/LeaderboardsViewData';
diff --git a/apps/website/templates/ProfileTemplate.tsx b/apps/website/templates/ProfileTemplate.tsx
index b88730482..b61ab3ecd 100644
--- a/apps/website/templates/ProfileTemplate.tsx
+++ b/apps/website/templates/ProfileTemplate.tsx
@@ -4,8 +4,8 @@ import React from 'react';
import { CreateDriverForm } from '@/components/drivers/CreateDriverForm';
import { ProfileRaceHistory } from '@/components/drivers/ProfileRaceHistory';
import { ProfileSettings } from '@/components/drivers/ProfileSettings';
-import { AchievementGrid } from '@/ui/AchievementGrid';
-import { ProfileHero } from '@/ui/ProfileHero';
+import { AchievementGrid } from '@/components/achievements/AchievementGrid';
+import { ProfileHero } from '@/components/drivers/ProfileHero';
import { ProfileStatGrid } from '@/ui/ProfileStatGrid';
import { ProfileTabs, type ProfileTab as ProfileTabsType } from '@/ui/ProfileTabs';
import { TeamMembershipGrid } from '@/ui/TeamMembershipGrid';
diff --git a/apps/website/templates/RaceDetailTemplate.tsx b/apps/website/templates/RaceDetailTemplate.tsx
index 8d708bad4..3254b3f17 100644
--- a/apps/website/templates/RaceDetailTemplate.tsx
+++ b/apps/website/templates/RaceDetailTemplate.tsx
@@ -15,9 +15,9 @@ import { InfoBox } from '@/ui/InfoBox';
import { RaceJoinButton } from '@/ui/RaceJoinButton';
import { RaceHero } from '@/ui/RaceHeroWrapper';
import { RaceUserResult } from '@/ui/RaceUserResultWrapper';
-import { RaceEntryList } from '@/ui/RaceEntryList';
+import { RaceEntryList } from '@/components/races/RaceEntryList';
import { RaceDetailCard } from '@/ui/RaceDetailCard';
-import { LeagueSummaryCard } from '@/ui/LeagueSummaryCardWrapper';
+import { LeagueSummaryCard } from '@/components/leagues/LeagueSummaryCardWrapper';
import {
AlertTriangle,
ArrowLeft,
diff --git a/apps/website/templates/RaceResultsTemplate.tsx b/apps/website/templates/RaceResultsTemplate.tsx
index 453929b91..c8421bd19 100644
--- a/apps/website/templates/RaceResultsTemplate.tsx
+++ b/apps/website/templates/RaceResultsTemplate.tsx
@@ -14,7 +14,7 @@ import { Icon } from '@/ui/Icon';
import { Surface } from '@/ui/Surface';
import { ArrowLeft, Trophy, Zap, type LucideIcon } from 'lucide-react';
import type { RaceResultsViewData } from '@/lib/view-data/races/RaceResultsViewData';
-import { RaceResultRow } from '@/ui/RaceResultRow';
+import { RaceResultRow } from '@/components/races/RaceResultRow';
import { RacePenaltyRow } from '@/ui/RacePenaltyRowWrapper';
export interface RaceResultsTemplateProps {
diff --git a/apps/website/templates/RaceStewardingTemplate.tsx b/apps/website/templates/RaceStewardingTemplate.tsx
index 421a0df5b..e2f74e99f 100644
--- a/apps/website/templates/RaceStewardingTemplate.tsx
+++ b/apps/website/templates/RaceStewardingTemplate.tsx
@@ -4,7 +4,7 @@ import React from 'react';
import { Breadcrumbs } from '@/ui/Breadcrumbs';
import { RaceStewardingStats } from '@/ui/RaceStewardingStats';
import { StewardingTabs } from '@/ui/StewardingTabs';
-import { ProtestCard } from '@/ui/ProtestCardWrapper';
+import { ProtestCard } from '@/components/leagues/ProtestCardWrapper';
import { RacePenaltyRow } from '@/ui/RacePenaltyRowWrapper';
import { Card } from '@/ui/Card';
import { Box } from '@/ui/Box';
diff --git a/apps/website/templates/RacesAllTemplate.tsx b/apps/website/templates/RacesAllTemplate.tsx
index ee7fefda7..5d9626e88 100644
--- a/apps/website/templates/RacesAllTemplate.tsx
+++ b/apps/website/templates/RacesAllTemplate.tsx
@@ -19,7 +19,7 @@ import { Container } from '@/ui/Container';
import { Icon } from '@/ui/Icon';
import { Surface } from '@/ui/Surface';
import { Skeleton } from '@/ui/Skeleton';
-import { RaceListItem } from '@/ui/RaceListItemWrapper';
+import { RaceListItem } from '@/components/races/RaceListItemWrapper';
import type { RacesViewData } from '@/lib/view-data/RacesViewData';
export type StatusFilter = 'scheduled' | 'running' | 'completed' | 'cancelled' | 'all';
diff --git a/apps/website/templates/RacesTemplate.tsx b/apps/website/templates/RacesTemplate.tsx
index 068597a18..16d954118 100644
--- a/apps/website/templates/RacesTemplate.tsx
+++ b/apps/website/templates/RacesTemplate.tsx
@@ -7,10 +7,10 @@ import { Container } from '@/ui/Container';
import { RaceFilterModal } from '@/ui/RaceFilterModal';
import type { RacesViewData } from '@/lib/view-data/RacesViewData';
import { RacePageHeader } from '@/ui/RacePageHeader';
-import { LiveRacesBanner } from '@/ui/LiveRacesBanner';
-import { RaceFilterBar } from '@/ui/RaceFilterBar';
-import { RaceList } from '@/ui/RaceList';
-import { RaceSidebar } from '@/ui/RaceSidebar';
+import { LiveRacesBanner } from '@/components/races/LiveRacesBanner';
+import { RaceFilterBar } from '@/components/races/RaceFilterBar';
+import { RaceList } from '@/components/races/RaceList';
+import { RaceSidebar } from '@/components/races/RaceSidebar';
import { Grid } from '@/ui/Grid';
import { GridItem } from '@/ui/GridItem';
diff --git a/apps/website/templates/TeamDetailTemplate.tsx b/apps/website/templates/TeamDetailTemplate.tsx
index fc7ea8d5d..d4c58439f 100644
--- a/apps/website/templates/TeamDetailTemplate.tsx
+++ b/apps/website/templates/TeamDetailTemplate.tsx
@@ -17,7 +17,7 @@ import { Text } from '@/ui/Text';
import { HorizontalStatItem } from '@/ui/HorizontalStatItem';
import { TeamAdmin } from '@/components/teams/TeamAdmin';
-import { TeamHero } from '@/ui/TeamHero';
+import { TeamHero } from '@/components/teams/TeamHero';
import { TeamRoster } from '@/components/teams/TeamRoster';
import { TeamStandings } from '@/components/teams/TeamStandings';
import type { TeamDetailViewData } from '@/lib/view-data/TeamDetailViewData';
diff --git a/apps/website/templates/TeamLeaderboardTemplate.tsx b/apps/website/templates/TeamLeaderboardTemplate.tsx
index a0d69cc85..b03011846 100644
--- a/apps/website/templates/TeamLeaderboardTemplate.tsx
+++ b/apps/website/templates/TeamLeaderboardTemplate.tsx
@@ -10,9 +10,9 @@ import { Text } from '@/ui/Text';
import { Container } from '@/ui/Container';
import { Icon } from '@/ui/Icon';
import { ModalIcon } from '@/ui/ModalIcon';
-import { TeamPodium } from '@/ui/TeamPodium';
+import { TeamPodium } from '@/components/teams/TeamPodium';
import { TeamFilter } from '@/ui/TeamFilter';
-import { TeamRankingsTable } from '@/ui/TeamRankingsTable';
+import { TeamRankingsTable } from '@/components/teams/TeamRankingsTable';
import type { TeamLeaderboardViewData, SkillLevel, SortBy } from '@/lib/view-data/TeamLeaderboardViewData';
interface TeamLeaderboardTemplateProps {
diff --git a/apps/website/templates/TeamsTemplate.tsx b/apps/website/templates/TeamsTemplate.tsx
index 8b6386ccd..39abe1f96 100644
--- a/apps/website/templates/TeamsTemplate.tsx
+++ b/apps/website/templates/TeamsTemplate.tsx
@@ -2,7 +2,7 @@
import React from 'react';
import { Users } from 'lucide-react';
-import { TeamLeaderboardPreview } from '@/ui/TeamLeaderboardPreviewWrapper';
+import { TeamLeaderboardPreview } from '@/components/teams/TeamLeaderboardPreviewWrapper';
import { Button } from '@/ui/Button';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
@@ -11,7 +11,7 @@ import { Heading } from '@/ui/Heading';
import { Container } from '@/ui/Container';
import { Grid } from '@/ui/Grid';
import { TeamCard } from '@/ui/TeamCardWrapper';
-import { EmptyState } from '@/ui/EmptyState';
+import { EmptyState } from '@/components/shared/state/EmptyState';
import type { TeamSummaryData, TeamsViewData } from '@/lib/view-data/TeamsViewData';
interface TeamsTemplateProps {
diff --git a/apps/website/ui/ActivityItem.tsx b/apps/website/ui/ActivityItem.tsx
index 73ea20385..73c9a2eca 100644
--- a/apps/website/ui/ActivityItem.tsx
+++ b/apps/website/ui/ActivityItem.tsx
@@ -3,6 +3,7 @@
import { Box } from './Box';
import { Link } from './Link';
import { Text } from './Text';
+import { Surface } from './Surface';
interface ActivityItemProps {
headline: string;
diff --git a/apps/website/ui/AvailableLeagueCard.tsx b/apps/website/ui/AvailableLeagueCard.tsx
index 6426b2572..a17350693 100644
--- a/apps/website/ui/AvailableLeagueCard.tsx
+++ b/apps/website/ui/AvailableLeagueCard.tsx
@@ -9,6 +9,7 @@ import { Heading } from './Heading';
import { Icon } from './Icon';
import { Link } from './Link';
import { Stack } from './Stack';
+import { Text } from './Text';
interface AvailableLeague {
id: string;
diff --git a/apps/website/ui/Box.tsx b/apps/website/ui/Box.tsx
index 9c8a13a48..3a34395b0 100644
--- a/apps/website/ui/Box.tsx
+++ b/apps/website/ui/Box.tsx
@@ -334,6 +334,7 @@ export const Box = forwardRef((
blur ? `blur-${blur}` : '',
animate ? `animate-${animate}` : '',
translateX ? `translate-x-${translateX}` : '',
+ textAlign ? `text-${textAlign}` : '',
hoverScale ? 'hover:scale-[1.02]' : '',
group ? 'group' : '',
groupHoverBorderColor ? `group-hover:border-${groupHoverBorderColor}` : '',
diff --git a/apps/website/ui/Button.tsx b/apps/website/ui/Button.tsx
index 9750f11ff..5d9dcacb5 100644
--- a/apps/website/ui/Button.tsx
+++ b/apps/website/ui/Button.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode, MouseEventHandler, ButtonHTMLAttributes, ElementType } from 'react';
+import React, { ReactNode, MouseEventHandler, ButtonHTMLAttributes, forwardRef } from 'react';
import { Stack } from './Stack';
import { Box, BoxProps } from './Box';
@@ -18,7 +18,7 @@ interface ButtonProps extends Omit, 'as'
rel?: string;
}
-export const Button = React.forwardRef(({
+export const Button = forwardRef(({
children,
onClick,
className = '',
@@ -79,7 +79,7 @@ export const Button = React.forwardRef(({
target={target}
rel={rel}
className={classes}
- {...(props as any)}
+ {...props}
>
{content}
@@ -89,12 +89,12 @@ export const Button = React.forwardRef(({
return (
{content}
@@ -102,5 +102,3 @@ export const Button = React.forwardRef(({
});
Button.displayName = 'Button';
-
-export default Button;
diff --git a/apps/website/ui/Card.tsx b/apps/website/ui/Card.tsx
index 3631a050e..47abfa97a 100644
--- a/apps/website/ui/Card.tsx
+++ b/apps/website/ui/Card.tsx
@@ -1,20 +1,26 @@
-import React, { ReactNode, MouseEventHandler, HTMLAttributes } from 'react';
+import React, { ReactNode, MouseEventHandler } from 'react';
import { Box, BoxProps } from './Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
+interface ResponsiveSpacing {
+ base?: Spacing;
+ md?: Spacing;
+ lg?: Spacing;
+}
+
interface CardProps extends Omit, 'children' | 'className' | 'onClick'> {
children: ReactNode;
className?: string;
onClick?: MouseEventHandler;
variant?: 'default' | 'highlight';
- p?: Spacing | any;
- px?: Spacing | any;
- py?: Spacing | any;
- pt?: Spacing | any;
- pb?: Spacing | any;
- pl?: Spacing | any;
- pr?: Spacing | any;
+ p?: Spacing | ResponsiveSpacing;
+ px?: Spacing | ResponsiveSpacing;
+ py?: Spacing | ResponsiveSpacing;
+ pt?: Spacing | ResponsiveSpacing;
+ pb?: Spacing | ResponsiveSpacing;
+ pl?: Spacing | ResponsiveSpacing;
+ pr?: Spacing | ResponsiveSpacing;
}
export function Card({
@@ -22,7 +28,6 @@ export function Card({
className = '',
onClick,
variant = 'default',
- p, px, py, pt, pb, pl, pr,
...props
}: CardProps) {
const baseClasses = 'rounded-lg shadow-card border duration-200';
@@ -32,29 +37,24 @@ export function Card({
highlight: 'bg-gradient-to-r from-blue-900/20 to-blue-700/10 border-blue-500/30'
};
- const spacingMap: Record = {
- 0: '0', 0.5: '0.5', 1: '1', 1.5: '1.5', 2: '2', 2.5: '2.5', 3: '3', 3.5: '3.5', 4: '4',
- 5: '5', 6: '6', 7: '7', 8: '8', 9: '9', 10: '10', 11: '11', 12: '12', 14: '14',
- 16: '16', 20: '20', 24: '24', 28: '28', 32: '32', 36: '36', 40: '40', 44: '44',
- 48: '48', 52: '52', 56: '56', 60: '60', 64: '64', 72: '72', 80: '80', 96: '96'
- };
-
const classes = [
baseClasses,
variantClasses[variant],
onClick ? 'cursor-pointer hover:scale-[1.02]' : '',
- p !== undefined ? `p-${spacingMap[p]}` : (px === undefined && py === undefined && pt === undefined && pb === undefined && pl === undefined && pr === undefined ? 'p-6' : ''),
- px !== undefined ? `px-${spacingMap[px]}` : '',
- py !== undefined ? `py-${spacingMap[py]}` : '',
- pt !== undefined ? `pt-${spacingMap[pt]}` : '',
- pb !== undefined ? `pb-${spacingMap[pb]}` : '',
- pl !== undefined ? `pl-${spacingMap[pl]}` : '',
- pr !== undefined ? `pr-${spacingMap[pr]}` : '',
className
].filter(Boolean).join(' ');
+ // Default padding if none provided
+ const hasPadding = props.p !== undefined || props.px !== undefined || props.py !== undefined ||
+ props.pt !== undefined || props.pb !== undefined || props.pl !== undefined || props.pr !== undefined;
+
return (
-
+
{children}
);
diff --git a/apps/website/ui/Container.tsx b/apps/website/ui/Container.tsx
index 3c467d748..551365f0e 100644
--- a/apps/website/ui/Container.tsx
+++ b/apps/website/ui/Container.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode, HTMLAttributes } from 'react';
+import React, { ReactNode } from 'react';
import { Box, BoxProps } from './Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
diff --git a/apps/website/ui/DashboardHero.tsx b/apps/website/ui/DashboardHero.tsx
index d432aa02b..f95f3058e 100644
--- a/apps/website/ui/DashboardHero.tsx
+++ b/apps/website/ui/DashboardHero.tsx
@@ -6,6 +6,7 @@ import { Box } from './Box';
import { Heading } from './Heading';
import { Image } from './Image';
import { Stack } from './Stack';
+import { Text } from './Text';
interface DashboardHeroProps {
driverName: string;
diff --git a/apps/website/ui/DiscordCTA.tsx b/apps/website/ui/DiscordCTA.tsx
index 7311442b8..6205df69e 100644
--- a/apps/website/ui/DiscordCTA.tsx
+++ b/apps/website/ui/DiscordCTA.tsx
@@ -7,6 +7,7 @@ import { DiscordIcon } from '@/ui/icons/DiscordIcon';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text';
+import { Grid } from '@/ui/Grid';
import { Code, Lightbulb, LucideIcon, MessageSquare, Users } from 'lucide-react';
export function DiscordCTA() {
@@ -77,7 +78,7 @@ export function DiscordCTA() {
- GridPilot is a solo developer project, and I'm building it because I got tired of the chaos in league racing.
+ GridPilot is a solo developer project, and I'm building it because I got tired of the chaos in league racing.
This is early days, and I need your help. Join the Discord to:
@@ -143,7 +144,7 @@ export function DiscordCTA() {
{/* Footer note */}
- This is a community effort. Every voice matters. Let's build something that actually works for league racing.
+ This is a community effort. Every voice matters. Let's build something that actually works for league racing.
@@ -186,5 +187,3 @@ function BenefitItem({ icon, title, description }: { icon: LucideIcon, title: st
);
}
-
-import { Grid } from '@/ui/Grid';
diff --git a/apps/website/ui/DurationField.tsx b/apps/website/ui/DurationField.tsx
index 133b6e282..91124f1fc 100644
--- a/apps/website/ui/DurationField.tsx
+++ b/apps/website/ui/DurationField.tsx
@@ -1,6 +1,6 @@
-import Input from '@/ui/Input';
+import { Input } from '@/ui/Input';
interface DurationFieldProps {
label: string;
@@ -13,7 +13,7 @@ interface DurationFieldProps {
error?: string;
}
-export default function DurationField({
+export function DurationField({
label,
value,
onChange,
diff --git a/apps/website/ui/FeedItem.tsx b/apps/website/ui/FeedItem.tsx
index 126004c6b..1b4730481 100644
--- a/apps/website/ui/FeedItem.tsx
+++ b/apps/website/ui/FeedItem.tsx
@@ -1,9 +1,7 @@
import React, { ReactNode } from 'react';
-import Image from 'next/image';
import { Box } from './Box';
-import { Stack } from './Stack';
import { Text } from './Text';
-import { Card } from './Card';
+import { Image } from './Image';
interface FeedItemProps {
actorName?: string;
@@ -34,7 +32,9 @@ export function FeedItem({
alt={actorName || ''}
width={40}
height={40}
- className="w-full h-full object-cover"
+ fullWidth
+ fullHeight
+ objectFit="cover"
/>
) : (
diff --git a/apps/website/ui/Footer.tsx b/apps/website/ui/Footer.tsx
index 35f61d5a1..c067d1a13 100644
--- a/apps/website/ui/Footer.tsx
+++ b/apps/website/ui/Footer.tsx
@@ -1,9 +1,6 @@
-'use client';
-
import { Image } from '@/ui/Image';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
-import { Stack } from '@/ui/Stack';
import { Link } from '@/ui/Link';
const discordUrl = process.env.NEXT_PUBLIC_DISCORD_URL || 'https://discord.gg/gridpilot';
diff --git a/apps/website/ui/Grid.tsx b/apps/website/ui/Grid.tsx
index 20db27813..1bc863c8a 100644
--- a/apps/website/ui/Grid.tsx
+++ b/apps/website/ui/Grid.tsx
@@ -6,7 +6,7 @@ interface GridProps extends Omit, 'children' | 'display'> {
cols?: 1 | 2 | 3 | 4 | 5 | 6 | 12;
mdCols?: 1 | 2 | 3 | 4 | 5 | 6 | 12;
lgCols?: 1 | 2 | 3 | 4 | 5 | 6 | 12;
- gap?: any;
+ gap?: 0 | 1 | 2 | 3 | 4 | 6 | 8 | 12 | 16;
}
export function Grid({
diff --git a/apps/website/ui/InfoBanner.tsx b/apps/website/ui/InfoBanner.tsx
index 9aaa1bbb4..0c54ec67a 100644
--- a/apps/website/ui/InfoBanner.tsx
+++ b/apps/website/ui/InfoBanner.tsx
@@ -75,7 +75,7 @@ export function InfoBanner({
{title && (
- {title}
+ {title}
)}
{children}
diff --git a/apps/website/ui/Input.tsx b/apps/website/ui/Input.tsx
index de56ec566..3767598be 100644
--- a/apps/website/ui/Input.tsx
+++ b/apps/website/ui/Input.tsx
@@ -1,9 +1,9 @@
-import React, { forwardRef } from 'react';
+import React, { forwardRef, InputHTMLAttributes } from 'react';
import { Text } from './Text';
import { Box } from './Box';
import { Stack } from './Stack';
-interface InputProps extends React.InputHTMLAttributes {
+interface InputProps extends InputHTMLAttributes {
variant?: 'default' | 'error';
errorMessage?: string;
icon?: React.ReactNode;
diff --git a/apps/website/ui/JoinRequestItem.tsx b/apps/website/ui/JoinRequestItem.tsx
index 0ef4051e7..b653863de 100644
--- a/apps/website/ui/JoinRequestItem.tsx
+++ b/apps/website/ui/JoinRequestItem.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode } from 'react';
+import React from 'react';
import { Box } from './Box';
import { Text } from './Text';
import { Stack } from './Stack';
diff --git a/apps/website/ui/LeagueCard.tsx b/apps/website/ui/LeagueCard.tsx
index eef707313..a92708ba2 100644
--- a/apps/website/ui/LeagueCard.tsx
+++ b/apps/website/ui/LeagueCard.tsx
@@ -5,6 +5,9 @@ import { Box } from './Box';
import { Heading } from './Heading';
import { Icon } from './Icon';
import { Text } from './Text';
+import { Image } from './Image';
+import { PlaceholderImage } from './PlaceholderImage';
+import { Calendar as LucideCalendar, ChevronRight as LucideChevronRight, Users as LucideUsers } from 'lucide-react';
interface LeagueCardProps {
name: string;
@@ -67,12 +70,13 @@ export function LeagueCard({
>
{/* Cover Image */}
-
{/* Gradient Overlay */}
@@ -91,14 +95,14 @@ export function LeagueCard({
{logoUrl ? (
-
) : (
@@ -193,5 +197,3 @@ export function LeagueCard({
);
}
-import { Calendar as LucideCalendar, ChevronRight as LucideChevronRight, Users as LucideUsers } from 'lucide-react';
-
diff --git a/apps/website/ui/LeagueHeader.tsx b/apps/website/ui/LeagueHeader.tsx
index cb2ca69a3..32be884e9 100644
--- a/apps/website/ui/LeagueHeader.tsx
+++ b/apps/website/ui/LeagueHeader.tsx
@@ -5,6 +5,7 @@ import { Box } from './Box';
import { Heading } from './Heading';
import { Stack } from './Stack';
import { Text } from './Text';
+import { Image } from './Image';
interface LeagueHeaderProps {
name: string;
@@ -26,14 +27,14 @@ export function LeagueHeader({
-
diff --git a/apps/website/ui/LeagueMemberTable.tsx b/apps/website/ui/LeagueMemberTable.tsx
index adf65d92c..54011d809 100644
--- a/apps/website/ui/LeagueMemberTable.tsx
+++ b/apps/website/ui/LeagueMemberTable.tsx
@@ -17,7 +17,7 @@ export function LeagueMemberTable({ children, showActions }: LeagueMemberTablePr
Wins
Role
Joined
- {showActions && Actions}
+ {showActions && Actions}
diff --git a/apps/website/ui/Link.tsx b/apps/website/ui/Link.tsx
index 30dc6db5e..f22a0febd 100644
--- a/apps/website/ui/Link.tsx
+++ b/apps/website/ui/Link.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode, AnchorHTMLAttributes, ElementType } from 'react';
+import React, { ReactNode } from 'react';
import { Box, BoxProps } from './Box';
interface LinkProps extends Omit, 'children' | 'className' | 'onClick'> {
@@ -70,7 +70,7 @@ export function Link({
className={classes}
target={target}
rel={rel}
- onClick={onClick as any}
+ onClick={onClick}
style={style}
{...props}
>
diff --git a/apps/website/ui/Podium.tsx b/apps/website/ui/Podium.tsx
index 45e6d7d0f..5f82a4591 100644
--- a/apps/website/ui/Podium.tsx
+++ b/apps/website/ui/Podium.tsx
@@ -60,7 +60,7 @@ export function PodiumItem({
p={3}
>
-
+
{position}
diff --git a/apps/website/ui/PresetCard.tsx b/apps/website/ui/PresetCard.tsx
index 2a803f2e6..8c77300c4 100644
--- a/apps/website/ui/PresetCard.tsx
+++ b/apps/website/ui/PresetCard.tsx
@@ -1,7 +1,7 @@
import type { MouseEventHandler, ReactNode } from 'react';
-import Card from './Card';
+import { Card } from './Card';
interface PresetCardStat {
label: string;
@@ -21,7 +21,7 @@ export interface PresetCardProps {
children?: ReactNode;
}
-export default function PresetCard({
+export function PresetCard({
title,
subtitle,
primaryTag,
diff --git a/apps/website/ui/ProfileStatGrid.tsx b/apps/website/ui/ProfileStatGrid.tsx
index c72a171a7..f14a6fa4a 100644
--- a/apps/website/ui/ProfileStatGrid.tsx
+++ b/apps/website/ui/ProfileStatGrid.tsx
@@ -19,7 +19,7 @@ export function ProfileStatGrid({ stats }: ProfileStatGridProps) {
{stats.map((stat, idx) => (
- {stat.value}
+ {stat.value}
{stat.label}
))}
diff --git a/apps/website/ui/RaceCard.tsx b/apps/website/ui/RaceCard.tsx
index 0aeec0581..1f60df311 100644
--- a/apps/website/ui/RaceCard.tsx
+++ b/apps/website/ui/RaceCard.tsx
@@ -74,7 +74,7 @@ export function RaceCard({
{scheduledAtDate.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
-
+
{status === 'running' ? 'LIVE' : scheduledAtDate.toLocaleDateString()}
@@ -128,9 +128,9 @@ export function RaceCard({
}}
>
{statusConfig.icon && (
-
+
)}
-
+
{statusConfig.label}
diff --git a/apps/website/ui/RaceSummaryItem.tsx b/apps/website/ui/RaceSummaryItem.tsx
index 048869c6f..a79ebb191 100644
--- a/apps/website/ui/RaceSummaryItem.tsx
+++ b/apps/website/ui/RaceSummaryItem.tsx
@@ -1,6 +1,5 @@
import React from 'react';
import { Box } from './Box';
-import { Stack } from './Stack';
import { Text } from './Text';
interface RaceSummaryItemProps {
diff --git a/apps/website/ui/RatingHistoryItem.tsx b/apps/website/ui/RatingHistoryItem.tsx
index dae365c8f..289a8fd79 100644
--- a/apps/website/ui/RatingHistoryItem.tsx
+++ b/apps/website/ui/RatingHistoryItem.tsx
@@ -3,6 +3,12 @@
import { Box } from './Box';
import { Text } from './Text';
+interface RatingHistoryItemProps {
+ date: string;
+ skillChange: number;
+ safetyChange: number;
+ sportsmanshipChange: number;
+}
export function RatingHistoryItem({
date,
diff --git a/apps/website/ui/SidebarActionLink.tsx b/apps/website/ui/SidebarActionLink.tsx
index 6fbd6a493..994d5d2e1 100644
--- a/apps/website/ui/SidebarActionLink.tsx
+++ b/apps/website/ui/SidebarActionLink.tsx
@@ -4,7 +4,6 @@ import { Box } from './Box';
import { Text } from './Text';
import { Icon } from './Icon';
import { Link } from './Link';
-import { Stack } from './Stack';
interface SidebarActionLinkProps {
href: string;
diff --git a/apps/website/ui/SidebarRaceItem.tsx b/apps/website/ui/SidebarRaceItem.tsx
index 0272966a9..2c9c703cd 100644
--- a/apps/website/ui/SidebarRaceItem.tsx
+++ b/apps/website/ui/SidebarRaceItem.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { ChevronRight } from 'lucide-react';
import { Box } from './Box';
-import { Stack } from './Stack';
import { Text } from './Text';
import { Icon } from './Icon';
diff --git a/apps/website/ui/SkillDistribution.tsx b/apps/website/ui/SkillDistribution.tsx
index 8f1144b31..2d6b87a64 100644
--- a/apps/website/ui/SkillDistribution.tsx
+++ b/apps/website/ui/SkillDistribution.tsx
@@ -4,6 +4,7 @@ import { Box } from '@/ui/Box';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Text } from '@/ui/Text';
+import { BarChart3 } from 'lucide-react';
const SKILL_LEVELS = [
{ id: 'pro', label: 'Pro', icon: BarChart3, color: 'text-yellow-400', bgColor: 'bg-yellow-400/10', borderColor: 'border-yellow-400/30' },
diff --git a/apps/website/ui/SkillLevelHeader.tsx b/apps/website/ui/SkillLevelHeader.tsx
index 37a18374a..669ecd0d8 100644
--- a/apps/website/ui/SkillLevelHeader.tsx
+++ b/apps/website/ui/SkillLevelHeader.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode } from 'react';
+import React from 'react';
import { LucideIcon, ChevronRight, UserPlus } from 'lucide-react';
import { Box } from './Box';
import { Stack } from './Stack';
diff --git a/apps/website/ui/SponsorMetricCard.tsx b/apps/website/ui/SponsorMetricCard.tsx
index 17adcd57f..3f9b83b36 100644
--- a/apps/website/ui/SponsorMetricCard.tsx
+++ b/apps/website/ui/SponsorMetricCard.tsx
@@ -2,11 +2,12 @@ import React from 'react';
import { Box } from './Box';
import { Text } from './Text';
import { Icon } from './Icon';
+import { LucideIcon } from 'lucide-react';
interface SponsorMetricCardProps {
label: string;
value: string | number;
- icon: React.ComponentType<{ className?: string }>;
+ icon: LucideIcon;
color?: string;
trend?: {
value: number;
@@ -30,7 +31,7 @@ export function SponsorMetricCard({
borderColor="border-charcoal-outline"
>
-
+
{label}
diff --git a/apps/website/ui/SponsorSlotCard.tsx b/apps/website/ui/SponsorSlotCard.tsx
index 05519ff01..d93ce54e5 100644
--- a/apps/website/ui/SponsorSlotCard.tsx
+++ b/apps/website/ui/SponsorSlotCard.tsx
@@ -1,7 +1,6 @@
import React, { ReactNode } from 'react';
import { Box } from './Box';
import { Text } from './Text';
-import { Stack } from './Stack';
interface SponsorSlotCardProps {
title: string;
diff --git a/apps/website/ui/SponsorshipRequestItem.tsx b/apps/website/ui/SponsorshipRequestItem.tsx
index 4b0764039..f8fc987ec 100644
--- a/apps/website/ui/SponsorshipRequestItem.tsx
+++ b/apps/website/ui/SponsorshipRequestItem.tsx
@@ -3,6 +3,7 @@
import { Building, Check, Clock, DollarSign, MessageCircle, X } from 'lucide-react';
import React from 'react';
import { Badge } from './Badge';
+import { Box } from './Box';
import { Button } from './Button';
import { Heading } from './Heading';
import { Icon } from './Icon';
diff --git a/apps/website/ui/Stack.tsx b/apps/website/ui/Stack.tsx
index 994e24b57..93d4b927b 100644
--- a/apps/website/ui/Stack.tsx
+++ b/apps/website/ui/Stack.tsx
@@ -11,6 +11,15 @@ interface ResponsiveGap {
xl?: number;
}
+interface ResponsiveSpacing {
+ base?: Spacing;
+ sm?: Spacing;
+ md?: Spacing;
+ lg?: Spacing;
+ xl?: Spacing;
+ '2xl'?: Spacing;
+}
+
interface StackProps extends Omit, 'children' | 'className' | 'gap'> {
children: ReactNode;
className?: string;
@@ -20,18 +29,18 @@ interface StackProps extends Omit, 'children'
justify?: 'start' | 'center' | 'end' | 'between' | 'around';
wrap?: boolean;
center?: boolean;
- m?: Spacing | any;
- mt?: Spacing | any;
- mb?: Spacing | any;
- ml?: Spacing | any;
- mr?: Spacing | any;
- p?: Spacing | any;
- pt?: Spacing | any;
- pb?: Spacing | any;
- pl?: Spacing | any;
- pr?: Spacing | any;
- px?: Spacing | any;
- py?: Spacing | any;
+ m?: Spacing | ResponsiveSpacing;
+ mt?: Spacing | ResponsiveSpacing;
+ mb?: Spacing | ResponsiveSpacing;
+ ml?: Spacing | ResponsiveSpacing;
+ mr?: Spacing | ResponsiveSpacing;
+ p?: Spacing | ResponsiveSpacing;
+ pt?: Spacing | ResponsiveSpacing;
+ pb?: Spacing | ResponsiveSpacing;
+ pl?: Spacing | ResponsiveSpacing;
+ pr?: Spacing | ResponsiveSpacing;
+ px?: Spacing | ResponsiveSpacing;
+ py?: Spacing | ResponsiveSpacing;
rounded?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
style?: React.CSSProperties;
role?: string;
@@ -99,6 +108,21 @@ export function Stack({
full: 'rounded-full'
};
+ const getSpacingClass = (prefix: string, value: Spacing | ResponsiveSpacing | undefined) => {
+ if (value === undefined) return '';
+ if (typeof value === 'object') {
+ const classes = [];
+ if (value.base !== undefined) classes.push(`${prefix}-${spacingMap[value.base]}`);
+ if (value.sm !== undefined) classes.push(`sm:${prefix}-${spacingMap[value.sm]}`);
+ if (value.md !== undefined) classes.push(`md:${prefix}-${spacingMap[value.md]}`);
+ if (value.lg !== undefined) classes.push(`lg:${prefix}-${spacingMap[value.lg]}`);
+ if (value.xl !== undefined) classes.push(`xl:${prefix}-${spacingMap[value.xl]}`);
+ if (value['2xl'] !== undefined) classes.push(`2xl:${prefix}-${spacingMap[value['2xl']]}`);
+ return classes.join(' ');
+ }
+ return `${prefix}-${spacingMap[value]}`;
+ };
+
const classes = [
'flex',
typeof direction === 'string'
@@ -111,18 +135,18 @@ export function Stack({
getGapClasses(gap) || 'gap-4',
center ? 'items-center justify-center' : `items-${align} justify-${justify}`,
wrap ? 'flex-wrap' : '',
- m !== undefined ? `m-${spacingMap[m]}` : '',
- mt !== undefined ? `mt-${spacingMap[mt]}` : '',
- mb !== undefined ? `mb-${spacingMap[mb]}` : '',
- ml !== undefined ? `ml-${spacingMap[ml]}` : '',
- mr !== undefined ? `mr-${spacingMap[mr]}` : '',
- p !== undefined ? `p-${spacingMap[p]}` : '',
- pt !== undefined ? `pt-${spacingMap[pt]}` : '',
- pb !== undefined ? `pb-${spacingMap[pb]}` : '',
- pl !== undefined ? `pl-${spacingMap[pl]}` : '',
- pr !== undefined ? `pr-${spacingMap[pr]}` : '',
- px !== undefined ? `px-${spacingMap[px]}` : '',
- py !== undefined ? `py-${spacingMap[py]}` : '',
+ getSpacingClass('m', m),
+ getSpacingClass('mt', mt),
+ getSpacingClass('mb', mb),
+ getSpacingClass('ml', ml),
+ getSpacingClass('mr', mr),
+ getSpacingClass('p', p),
+ getSpacingClass('pt', pt),
+ getSpacingClass('pb', pb),
+ getSpacingClass('pl', pl),
+ getSpacingClass('pr', pr),
+ getSpacingClass('px', px),
+ getSpacingClass('py', py),
rounded ? roundedClasses[rounded] : '',
className
].filter(Boolean).join(' ');
diff --git a/apps/website/ui/StatCard.tsx b/apps/website/ui/StatCard.tsx
index 37c434c72..b62a2548d 100644
--- a/apps/website/ui/StatCard.tsx
+++ b/apps/website/ui/StatCard.tsx
@@ -51,13 +51,6 @@ export function StatCard({
green: 'text-performance-green',
orange: 'text-warning-amber'
};
-
- const iconHexColors = {
- blue: '#3b82f6',
- purple: '#a78bfa',
- green: '#34d399',
- orange: '#fb923c'
- };
const cardContent = (
diff --git a/apps/website/ui/StatusIndicator.tsx b/apps/website/ui/StatusIndicator.tsx
index 8ed7db387..713891f81 100644
--- a/apps/website/ui/StatusIndicator.tsx
+++ b/apps/website/ui/StatusIndicator.tsx
@@ -4,6 +4,7 @@ import { LucideIcon } from 'lucide-react';
import React from 'react';
import { Box } from './Box';
import { Text } from './Text';
+import { Icon } from './Icon';
interface StatusIndicatorProps {
icon: LucideIcon;
diff --git a/apps/website/ui/Surface.tsx b/apps/website/ui/Surface.tsx
index ce90467de..48c586e22 100644
--- a/apps/website/ui/Surface.tsx
+++ b/apps/website/ui/Surface.tsx
@@ -80,7 +80,7 @@ export function Surface({
].filter(Boolean).join(' ');
return (
-
+
{children}
);
diff --git a/apps/website/ui/TabNavigation.tsx b/apps/website/ui/TabNavigation.tsx
index 372e8f1b6..7813ea626 100644
--- a/apps/website/ui/TabNavigation.tsx
+++ b/apps/website/ui/TabNavigation.tsx
@@ -2,11 +2,12 @@ import React from 'react';
import { Box } from './Box';
import { Text } from './Text';
import { Icon } from './Icon';
+import { LucideIcon } from 'lucide-react';
interface Tab {
id: string;
label: string;
- icon?: any;
+ icon?: LucideIcon;
}
interface TabNavigationProps {
diff --git a/apps/website/ui/Table.tsx b/apps/website/ui/Table.tsx
index 00ee3651e..9a594ad09 100644
--- a/apps/website/ui/Table.tsx
+++ b/apps/website/ui/Table.tsx
@@ -1,4 +1,4 @@
-import React, { ReactNode, HTMLAttributes, ElementType } from 'react';
+import React, { ReactNode, HTMLAttributes } from 'react';
import { Box, BoxProps } from './Box';
interface TableProps extends HTMLAttributes {
diff --git a/apps/website/ui/TeamCard.tsx b/apps/website/ui/TeamCard.tsx
index 6ea2713a3..e2c515839 100644
--- a/apps/website/ui/TeamCard.tsx
+++ b/apps/website/ui/TeamCard.tsx
@@ -6,6 +6,7 @@ import {
UserPlus,
Users
} from 'lucide-react';
+import { ReactNode } from 'react';
import { Badge } from './Badge';
import { Box } from './Box';
import { Card } from './Card';
@@ -69,7 +70,9 @@ export function TeamCard({
alt={name}
width={56}
height={56}
- style={{ width: '100%', height: '100%', objectFit: 'cover' }}
+ fullWidth
+ fullHeight
+ objectFit="cover"
/>
) : (
diff --git a/apps/website/ui/TeamLeaderboardItem.tsx b/apps/website/ui/TeamLeaderboardItem.tsx
index bc109fbff..491ddd62a 100644
--- a/apps/website/ui/TeamLeaderboardItem.tsx
+++ b/apps/website/ui/TeamLeaderboardItem.tsx
@@ -1,6 +1,6 @@
-import { Crown, Users } from 'lucide-react';
+import { Crown, Trophy, Users } from 'lucide-react';
import { Box } from './Box';
import { Icon } from './Icon';
import { Image } from './Image';
diff --git a/apps/website/ui/Text.tsx b/apps/website/ui/Text.tsx
index da6e40b70..c3c9c2e21 100644
--- a/apps/website/ui/Text.tsx
+++ b/apps/website/ui/Text.tsx
@@ -1,5 +1,5 @@
import React, { ReactNode, ElementType, ComponentPropsWithoutRef } from 'react';
-import { Box, BoxProps } from './Box';
+import { BoxProps } from './Box';
type Spacing = 0 | 0.5 | 1 | 1.5 | 2 | 2.5 | 3 | 3.5 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 | 52 | 56 | 60 | 64 | 72 | 80 | 96;
@@ -42,10 +42,19 @@ interface TextProps extends Omit, 'c
style?: React.CSSProperties;
block?: boolean;
italic?: boolean;
- ml?: Spacing | any;
- mr?: Spacing | any;
- mt?: Spacing | any;
- mb?: Spacing | any;
+ ml?: Spacing | ResponsiveSpacing;
+ mr?: Spacing | ResponsiveSpacing;
+ mt?: Spacing | ResponsiveSpacing;
+ mb?: Spacing | ResponsiveSpacing;
+}
+
+interface ResponsiveSpacing {
+ base?: Spacing;
+ sm?: Spacing;
+ md?: Spacing;
+ lg?: Spacing;
+ xl?: Spacing;
+ '2xl'?: Spacing;
}
export function Text({
@@ -146,6 +155,21 @@ export function Text({
loose: 'leading-loose'
};
+ const getSpacingClass = (prefix: string, value: Spacing | ResponsiveSpacing | undefined) => {
+ if (value === undefined) return '';
+ if (typeof value === 'object') {
+ const classes = [];
+ if (value.base !== undefined) classes.push(`${prefix}-${spacingMap[value.base as number]}`);
+ if (value.sm !== undefined) classes.push(`sm:${prefix}-${spacingMap[value.sm as number]}`);
+ if (value.md !== undefined) classes.push(`md:${prefix}-${spacingMap[value.md as number]}`);
+ if (value.lg !== undefined) classes.push(`lg:${prefix}-${spacingMap[value.lg as number]}`);
+ if (value.xl !== undefined) classes.push(`xl:${prefix}-${spacingMap[value.xl as number]}`);
+ if (value['2xl'] !== undefined) classes.push(`2xl:${prefix}-${spacingMap[value['2xl'] as number]}`);
+ return classes.join(' ');
+ }
+ return `${prefix}-${spacingMap[value as number]}`;
+ };
+
const classes = [
block ? 'block' : 'inline',
getSizeClasses(size),
@@ -158,10 +182,10 @@ export function Text({
uppercase ? 'uppercase' : '',
italic ? 'italic' : '',
letterSpacing === '0.05em' ? 'tracking-wider' : letterSpacing ? `tracking-${letterSpacing}` : '',
- ml !== undefined ? `ml-${spacingMap[ml]}` : '',
- mr !== undefined ? `mr-${spacingMap[mr]}` : '',
- mt !== undefined ? `mt-${spacingMap[mt]}` : '',
- mb !== undefined ? `mb-${spacingMap[mb]}` : '',
+ getSpacingClass('ml', ml),
+ getSpacingClass('mr', mr),
+ getSpacingClass('mt', mt),
+ getSpacingClass('mb', mb),
className
].filter(Boolean).join(' ');
diff --git a/apps/website/ui/state-types.ts b/apps/website/ui/state-types.ts
index 003a93801..7c5885069 100644
--- a/apps/website/ui/state-types.ts
+++ b/apps/website/ui/state-types.ts
@@ -80,6 +80,7 @@ export interface StateContainerConfig {
loading?: () => ReactNode;
error?: (error: Error) => ReactNode;
empty?: () => ReactNode;
+ success?: (data: T) => ReactNode;
};
}