website refactor

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

View File

@@ -5,7 +5,6 @@ import { Button } from '@/ui/Button';
import { Input } from '@/ui/Input';
import { TextArea } from '@/ui/TextArea';
import { useCreateTeam } from "@/hooks/team/useCreateTeam";
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { InfoBanner } from '@/ui/InfoBanner';
@@ -80,7 +79,7 @@ export function CreateTeamForm({ onCancel, onSuccess, onNavigate }: CreateTeamFo
};
return (
<Box as="form" onSubmit={handleSubmit}>
<Stack as="form" onSubmit={handleSubmit}>
<Stack gap={6}>
<Input
label="Team Name *"
@@ -125,7 +124,7 @@ export function CreateTeamForm({ onCancel, onSuccess, onNavigate }: CreateTeamFo
</Stack>
</InfoBanner>
<Box display="flex" gap={3}>
<Stack display="flex" gap={3}>
<Button
type="submit"
variant="primary"
@@ -144,8 +143,8 @@ export function CreateTeamForm({ onCancel, onSuccess, onNavigate }: CreateTeamFo
Cancel
</Button>
)}
</Box>
</Stack>
</Stack>
</Box>
</Stack>
);
}

View File

@@ -3,7 +3,6 @@
import React from 'react';
import { UserPlus } from 'lucide-react';
import { getMediaUrl } from '@/lib/utilities/media';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
@@ -32,9 +31,9 @@ export function FeaturedRecruiting({ teams, onTeamClick }: FeaturedRecruitingPro
if (recruitingTeams.length === 0) return null;
return (
<Box mb={10}>
<Stack mb={10}>
<Stack direction="row" align="center" gap={3} mb={4}>
<Box
<Stack
display="flex"
center
width="10"
@@ -45,11 +44,11 @@ export function FeaturedRecruiting({ teams, onTeamClick }: FeaturedRecruitingPro
borderColor="border-performance-green/20"
>
<Icon icon={UserPlus} size={5} color="text-performance-green" />
</Box>
<Box>
</Stack>
<Stack>
<Heading level={2}>Looking for Drivers</Heading>
<Text size="xs" color="text-gray-500">Teams actively recruiting new members</Text>
</Box>
</Stack>
</Stack>
<RecruitingTeamGrid>
@@ -66,6 +65,6 @@ export function FeaturedRecruiting({ teams, onTeamClick }: FeaturedRecruitingPro
/>
))}
</RecruitingTeamGrid>
</Box>
</Stack>
);
}

View File

@@ -1,8 +1,7 @@
import React from 'react';
import { Users, Trophy } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Image } from '@/ui/Image';
import { Icon } from '@/ui/Icon';
import { Badge } from '@/ui/Badge';
@@ -27,7 +26,7 @@ export function RecruitingTeamCard({
onClick,
}: RecruitingTeamCardProps) {
return (
<Box
<Stack
as="button"
type="button"
onClick={onClick}
@@ -38,8 +37,8 @@ export function RecruitingTeamCard({
borderColor="border-charcoal-outline"
className="hover:border-performance-green/40 transition-all duration-200 text-left group"
>
<Box display="flex" alignItems="start" justifyContent="between" mb={3}>
<Box width="8" height="8" rounded="lg" bg="bg-charcoal-outline" border={true} borderColor="border-charcoal-outline" overflow="hidden">
<Stack display="flex" alignItems="start" justifyContent="between" mb={3}>
<Stack width="8" height="8" rounded="lg" bg="bg-charcoal-outline" border={true} borderColor="border-charcoal-outline" overflow="hidden">
<Image
src={logoUrl}
alt={name}
@@ -47,12 +46,12 @@ export function RecruitingTeamCard({
height={32}
objectFit="cover"
/>
</Box>
</Stack>
<Badge variant="success">
<Box w="1.5" h="1.5" rounded="full" bg="bg-performance-green" animate="pulse" mr={1} />
<Stack w="1.5" h="1.5" rounded="full" bg="bg-performance-green" animate="pulse" mr={1} />
Recruiting
</Badge>
</Box>
</Stack>
<Text color="text-white" weight="semibold" block mb={1} className="group-hover:text-performance-green transition-colors line-clamp-1">
{name}
@@ -62,7 +61,7 @@ export function RecruitingTeamCard({
<Stack direction="row" align="center" gap={2} wrap>
{category && (
<Stack direction="row" align="center" gap={1}>
<Box w="1.5" h="1.5" rounded="full" bg="bg-purple-400" />
<Stack w="1.5" h="1.5" rounded="full" bg="bg-purple-400" />
<Text size="xs" color="text-purple-400">{category}</Text>
</Stack>
)}
@@ -75,6 +74,6 @@ export function RecruitingTeamCard({
<Text size="xs" color="text-gray-400">{totalWins} wins</Text>
</Stack>
</Stack>
</Box>
</Stack>
);
}

View File

@@ -5,7 +5,6 @@ import { Card } from '@/ui/Card';
import { Button } from '@/ui/Button';
import { Input } from '@/ui/Input';
import { TextArea } from '@/ui/TextArea';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
@@ -100,18 +99,18 @@ export function TeamAdmin({ team, onUpdate }: TeamAdminProps) {
return (
<Stack gap={6}>
<Card>
<Box display="flex" alignItems="center" justifyContent="between" mb={6}>
<Stack display="flex" alignItems="center" justifyContent="between" mb={6}>
<Heading level={3}>Team Settings</Heading>
{!editMode && (
<Button variant="secondary" onClick={() => setEditMode(true)}>
Edit Details
</Button>
)}
</Box>
</Stack>
{editMode ? (
<Stack gap={4}>
<Box>
<Stack>
<Text as="label" size="sm" weight="medium" color="text-gray-400" block mb={2}>
Team Name
</Text>
@@ -120,9 +119,9 @@ export function TeamAdmin({ team, onUpdate }: TeamAdminProps) {
value={editedTeam.name}
onChange={(e) => setEditedTeam({ ...editedTeam, name: e.target.value })}
/>
</Box>
</Stack>
<Box>
<Stack>
<Text as="label" size="sm" weight="medium" color="text-gray-400" block mb={2}>
Team Tag
</Text>
@@ -133,7 +132,7 @@ export function TeamAdmin({ team, onUpdate }: TeamAdminProps) {
maxLength={4}
/>
<Text size="xs" color="text-gray-500" block mt={1}>Max 4 characters</Text>
</Box>
</Stack>
<TextArea
label="Description"
@@ -163,18 +162,18 @@ export function TeamAdmin({ team, onUpdate }: TeamAdminProps) {
</Stack>
) : (
<Stack gap={4}>
<Box>
<Stack>
<Text size="sm" color="text-gray-400" block>Team Name</Text>
<Text color="text-white" weight="medium" block>{team.name}</Text>
</Box>
<Box>
</Stack>
<Stack>
<Text size="sm" color="text-gray-400" block>Team Tag</Text>
<Text color="text-white" weight="medium" block>{team.tag}</Text>
</Box>
<Box>
</Stack>
<Stack>
<Text size="sm" color="text-gray-400" block>Description</Text>
<Text color="text-white" block>{team.description}</Text>
</Box>
</Stack>
</Stack>
)}
</Card>
@@ -183,9 +182,9 @@ export function TeamAdmin({ team, onUpdate }: TeamAdminProps) {
<Heading level={3} mb={6}>Join Requests</Heading>
{loading ? (
<Box textAlign="center" py={8}>
<Stack textAlign="center" py={8}>
<Text color="text-gray-400">Loading requests...</Text>
</Box>
</Stack>
) : joinRequests.length > 0 ? (
<JoinRequestList>
{joinRequests.map((request: TeamJoinRequestViewModel) => (

View File

@@ -7,13 +7,12 @@ import {
} from 'lucide-react';
import { ReactNode } from 'react';
import { Badge } from '@/ui/Badge';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Icon } from '@/ui/Icon';
import { Image } from '@/ui/Image';
import { PlaceholderImage } from '@/ui/PlaceholderImage';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
interface TeamCardProps {
@@ -46,13 +45,13 @@ export function TeamCard({
onClick,
}: TeamCardProps) {
return (
<Box onClick={onClick} h="full" cursor={onClick ? 'pointer' : 'default'} className="group">
<Stack onClick={onClick} h="full" cursor={onClick ? 'pointer' : 'default'} className="group">
<Card h="full" p={0} display="flex" flexDirection="col" overflow="hidden" className="bg-panel-gray/40 border-border-gray/50 hover:border-primary-accent/30 hover:bg-panel-gray/60 transition-all duration-300">
{/* Header with Logo */}
<Box p={5} pb={0}>
<Stack p={5} pb={0}>
<Stack direction="row" align="start" gap={4}>
{/* Logo */}
<Box
<Stack
w="16"
h="16"
rounded="none"
@@ -77,11 +76,11 @@ export function TeamCard({
) : (
<PlaceholderImage size={64} />
)}
<Box position="absolute" top="-1px" left="-1px" w="2" h="2" borderTop borderLeft borderColor="primary-accent/30" />
</Box>
<Stack position="absolute" top="-1px" left="-1px" w="2" h="2" borderTop borderLeft borderColor="primary-accent/30" />
</Stack>
{/* Title & Badges */}
<Box flexGrow={1} minWidth="0">
<Stack flexGrow={1} minWidth="0">
<Stack direction="row" align="start" justify="between" gap={2}>
<Heading level={4} weight="bold" fontSize="lg" className="tracking-tight group-hover:text-primary-accent transition-colors">
{name}
@@ -99,12 +98,12 @@ export function TeamCard({
{specializationContent}
{categoryBadge}
</Stack>
</Box>
</Stack>
</Stack>
</Box>
</Stack>
{/* Content */}
<Box p={5} display="flex" flexDirection="col" flexGrow={1}>
<Stack p={5} display="flex" flexDirection="col" flexGrow={1}>
{/* Description */}
<Text
size="xs"
@@ -122,7 +121,7 @@ export function TeamCard({
{(region || languagesContent) && (
<Stack direction="row" align="center" gap={2} wrap mb={4}>
{region && (
<Box
<Stack
display="flex"
alignItems="center"
gap={2}
@@ -135,17 +134,17 @@ export function TeamCard({
>
<Icon icon={Globe} size={3} color="text-primary-accent" />
<Text size="xs" color="text-gray-400" weight="bold" className="uppercase tracking-widest">{region}</Text>
</Box>
</Stack>
)}
{languagesContent}
</Stack>
)}
{/* Spacer */}
<Box flexGrow={1} />
<Stack flexGrow={1} />
{/* Footer */}
<Box
<Stack
display="flex"
alignItems="center"
justifyContent="between"
@@ -165,9 +164,9 @@ export function TeamCard({
<Text size="xs" color="text-gray-500" weight="bold" className="uppercase tracking-widest">VIEW</Text>
<Icon icon={ChevronRight} size={3} color="text-gray-500" className="transition-transform group-hover:translate-x-0.5" />
</Stack>
</Box>
</Box>
</Stack>
</Stack>
</Card>
</Box>
</Stack>
);
}

View File

@@ -8,7 +8,6 @@ import {
TrendingUp,
Shield
} from 'lucide-react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Badge } from '@/ui/Badge';
@@ -102,12 +101,12 @@ export function TeamCard({
)}
categoryBadge={category && (
<Badge variant="primary">
<Box w="2" h="2" rounded="full" bg="bg-purple-500" mr={1.5} />
<Stack w="2" h="2" rounded="full" bg="bg-purple-500" mr={1.5} />
{category}
</Badge>
)}
languagesContent={languages && languages.length > 0 && (
<Box
<Stack
display="flex"
alignItems="center"
gap={1.5}
@@ -123,7 +122,7 @@ export function TeamCard({
{languages.slice(0, 2).join(', ')}
{languages.length > 2 && ` +${languages.length - 2}`}
</Text>
</Box>
</Stack>
)}
statsContent={
<>

View File

@@ -1,7 +1,6 @@
'use client';
import React from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
@@ -31,7 +30,7 @@ export function TeamDetailsHeader({
onAdminClick,
}: TeamDetailsHeaderProps) {
return (
<Box
<Stack
bg="surface-charcoal"
border
borderColor="outline-steel"
@@ -40,7 +39,7 @@ export function TeamDetailsHeader({
overflow="hidden"
>
{/* Background accent */}
<Box
<Stack
position="absolute"
top="0"
right="0"
@@ -53,7 +52,7 @@ export function TeamDetailsHeader({
/>
<Stack direction="row" align="start" gap={8} position="relative">
<Box
<Stack
w="32"
h="32"
bg="base-black"
@@ -68,15 +67,15 @@ export function TeamDetailsHeader({
) : (
<Text size="2xl" weight="bold" color="text-gray-700">{name.substring(0, 2).toUpperCase()}</Text>
)}
</Box>
</Stack>
<Box flex="1">
<Stack flex="1">
<Stack direction="row" align="center" gap={3}>
<Heading level={1} weight="bold">{name}</Heading>
{tag && (
<Box px={2} py={1} bg="base-black" border borderColor="outline-steel">
<Stack px={2} py={1} bg="base-black" border borderColor="outline-steel">
<Text size="xs" font="mono" color="primary-accent" weight="bold">[{tag}]</Text>
</Box>
</Stack>
)}
</Stack>
@@ -85,18 +84,18 @@ export function TeamDetailsHeader({
</Text>
<Stack direction="row" gap={6} mt={6}>
<Box>
<Stack>
<Text size="xs" color="text-gray-500" uppercase font="mono" letterSpacing="widest">Personnel</Text>
<Text block weight="bold" color="text-white">{memberCount} Units</Text>
</Box>
<Box>
</Stack>
<Stack>
<Text size="xs" color="text-gray-500" uppercase font="mono" letterSpacing="widest">Established</Text>
<Text block weight="bold" color="text-white">
{foundedDate ? new Date(foundedDate).toLocaleDateString() : 'Unknown'}
</Text>
</Box>
</Stack>
</Stack>
</Box>
</Stack>
<Stack gap={3}>
{isAdmin && (
@@ -109,6 +108,6 @@ export function TeamDetailsHeader({
</Button>
</Stack>
</Stack>
</Box>
</Stack>
);
}

View File

@@ -3,7 +3,6 @@ import { Search, Star, Trophy, Percent, Hash, LucideIcon } from 'lucide-react';
import { Button } from '@/ui/Button';
import { Input } from '@/ui/Input';
import { Stack } from '@/ui/Stack';
import { Box } from '@/ui/Box';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { Badge } from '@/ui/Badge';
@@ -50,7 +49,7 @@ export function TeamFilter({
<Stack mb={6} gap={4}>
{/* Search and Level Filter Row */}
<Stack direction="row" align="center" gap={4} wrap>
<Box maxWidth="448px" fullWidth>
<Stack maxWidth="448px" fullWidth>
<Input
type="text"
placeholder="Search teams..."
@@ -58,7 +57,7 @@ export function TeamFilter({
onChange={(e) => onSearchChange(e.target.value)}
icon={<Icon icon={Search} size={5} color="text-gray-500" />}
/>
</Box>
</Stack>
{/* Level Filter */}
<Stack direction="row" align="center" gap={2} wrap>
@@ -92,7 +91,7 @@ export function TeamFilter({
{/* Sort Options */}
<Stack direction="row" align="center" gap={2}>
<Text size="sm" color="text-gray-400">Sort by:</Text>
<Box p={1} rounded="lg" border={true} borderColor="border-charcoal-outline" bg="bg-iron-gray" bgOpacity={0.5}>
<Stack p={1} rounded="lg" border={true} borderColor="border-charcoal-outline" bg="bg-iron-gray" bgOpacity={0.5}>
<Stack direction="row" align="center" gap={1}>
{SORT_OPTIONS.map((option) => {
const isActive = sortBy === option.id;
@@ -109,7 +108,7 @@ export function TeamFilter({
);
})}
</Stack>
</Box>
</Stack>
</Stack>
</Stack>
);

View File

@@ -1,5 +1,4 @@
import React, { ReactNode } from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
@@ -30,7 +29,7 @@ export function TeamHeaderPanel({
actions,
}: TeamHeaderPanelProps) {
return (
<Box
<Stack
bg="surface-charcoal"
border
borderColor="border-steel-grey"
@@ -38,12 +37,12 @@ export function TeamHeaderPanel({
className="relative overflow-hidden"
>
{/* Instrument-grade accent corner */}
<Box position="absolute" top="-1px" left="-1px" w="4" h="4" borderTop borderLeft borderColor="primary-blue/40" />
<Stack position="absolute" top="-1px" left="-1px" w="4" h="4" borderTop borderLeft borderColor="primary-blue/40" />
<Stack direction="row" align="start" justify="between" wrap gap={6}>
<Stack direction="row" align="start" gap={6} wrap flexGrow={1}>
{/* Logo Container */}
<Box
<Stack
w="24"
h="24"
bg="base-graphite"
@@ -56,10 +55,10 @@ export function TeamHeaderPanel({
>
<TeamLogo teamId={teamId} alt={name} />
{/* Corner detail */}
<Box position="absolute" bottom="0" right="0" w="2" h="2" bg="primary-blue/20" />
</Box>
<Stack position="absolute" bottom="0" right="0" w="2" h="2" bg="primary-blue/20" />
</Stack>
<Box flexGrow={1} minWidth="0">
<Stack flexGrow={1} minWidth="0">
<Stack direction="row" align="center" gap={3} mb={2}>
<Heading level={1} weight="bold" className="tracking-tight">{name}</Heading>
{tag && <TeamTag tag={tag} />}
@@ -72,29 +71,29 @@ export function TeamHeaderPanel({
)}
<Stack direction="row" align="center" gap={4} wrap>
<Box display="flex" alignItems="center" gap={1.5}>
<Box w="1.5" h="1.5" bg="primary-blue" />
<Stack display="flex" alignItems="center" gap={1.5}>
<Stack w="1.5" h="1.5" bg="primary-blue" />
<Text size="xs" color="text-gray-300" font="mono" className="uppercase tracking-wider">
{memberCount} {memberCount === 1 ? 'Member' : 'Members'}
</Text>
</Box>
</Stack>
{category && (
<Box display="flex" alignItems="center" gap={1.5}>
<Box w="1.5" h="1.5" bg="telemetry-aqua" />
<Stack display="flex" alignItems="center" gap={1.5}>
<Stack w="1.5" h="1.5" bg="telemetry-aqua" />
<Text size="xs" color="text-gray-300" font="mono" className="uppercase tracking-wider">
{category}
</Text>
</Box>
</Stack>
)}
{activeLeaguesCount !== undefined && (
<Box display="flex" alignItems="center" gap={1.5}>
<Box w="1.5" h="1.5" bg="warning-amber" />
<Stack display="flex" alignItems="center" gap={1.5}>
<Stack w="1.5" h="1.5" bg="warning-amber" />
<Text size="xs" color="text-gray-300" font="mono" className="uppercase tracking-wider">
{activeLeaguesCount} {activeLeaguesCount === 1 ? 'League' : 'Leagues'}
</Text>
</Box>
</Stack>
)}
{foundedDate && (
@@ -103,15 +102,15 @@ export function TeamHeaderPanel({
</Text>
)}
</Stack>
</Box>
</Stack>
</Stack>
{actions && (
<Box>
<Stack>
{actions}
</Box>
</Stack>
)}
</Stack>
</Box>
</Stack>
);
}

View File

@@ -1,10 +1,9 @@
import { JoinTeamButton } from '@/components/teams/JoinTeamButton';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Card } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { TeamLogo } from '@/components/teams/TeamLogo';
import { TeamTag } from '@/components/teams/TeamTag';
import { Text } from '@/ui/Text';
@@ -28,7 +27,7 @@ export function TeamHero({ team, memberCount, onUpdate }: TeamHeroProps) {
<Card>
<Stack direction="row" align="start" justify="between" wrap gap={6}>
<Stack direction="row" align="start" gap={6} wrap flexGrow={1}>
<Box
<Stack
w="24"
h="24"
rounded="lg"
@@ -40,9 +39,9 @@ export function TeamHero({ team, memberCount, onUpdate }: TeamHeroProps) {
justifyContent="center"
>
<TeamLogo teamId={team.id} alt={team.name} />
</Box>
</Stack>
<Box flexGrow={1} minWidth="0">
<Stack flexGrow={1} minWidth="0">
<Stack direction="row" align="center" gap={3} mb={2}>
<Heading level={1}>{team.name}</Heading>
{team.tag && <TeamTag tag={team.tag} />}
@@ -54,7 +53,7 @@ export function TeamHero({ team, memberCount, onUpdate }: TeamHeroProps) {
<Text size="sm" color="text-gray-400">{memberCount} {memberCount === 1 ? 'member' : 'members'}</Text>
{team.category && (
<Stack direction="row" align="center" gap={1.5}>
<Box w="2" h="2" rounded="full" bg="bg-purple-500" />
<Stack w="2" h="2" rounded="full" bg="bg-purple-500" />
<Text size="sm" color="text-purple-400">{team.category}</Text>
</Stack>
)}
@@ -69,7 +68,7 @@ export function TeamHero({ team, memberCount, onUpdate }: TeamHeroProps) {
</Text>
)}
</Stack>
</Box>
</Stack>
</Stack>
<JoinTeamButton teamId={team.id} onUpdate={onUpdate} />

View File

@@ -3,9 +3,8 @@
import { Users } from 'lucide-react';
import { ReactNode } from 'react';
import { Badge } from '@/ui/Badge';
import { Box } from '@/ui/Box';
import { Heading } from '@/ui/Heading';
import { Stack } from '@/ui/Stack';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
interface TeamHeroSectionProps {
@@ -24,9 +23,9 @@ export function TeamHeroSection({
sideContent,
}: TeamHeroSectionProps) {
return (
<Box position="relative" mb={10} overflow="hidden">
<Stack position="relative" mb={10} overflow="hidden">
{/* Main Hero Card */}
<Box
<Stack
position="relative"
py={12}
px={8}
@@ -36,19 +35,19 @@ export function TeamHeroSection({
border
>
{/* Background decorations */}
<Box position="absolute" top="0" right="0" w="80" h="80" bg="bg-purple-500" bgOpacity={0.1} rounded="full" blur="3xl" />
<Box position="absolute" bottom="0" left="1/4" w="64" h="64" bg="bg-neon-aqua" bgOpacity={0.05} rounded="full" blur="3xl" />
<Box position="absolute" top="1/2" right="1/4" w="48" h="48" bg="bg-yellow-400" bgOpacity={0.05} rounded="full" blur="2xl" />
<Stack position="absolute" top="0" right="0" w="80" h="80" bg="bg-purple-500" bgOpacity={0.1} rounded="full" blur="3xl" />
<Stack position="absolute" bottom="0" left="1/4" w="64" h="64" bg="bg-neon-aqua" bgOpacity={0.05} rounded="full" blur="3xl" />
<Stack position="absolute" top="1/2" right="1/4" w="48" h="48" bg="bg-yellow-400" bgOpacity={0.05} rounded="full" blur="2xl" />
<Box position="relative" zIndex={10}>
<Stack position="relative" zIndex={10}>
<Stack direction={{ base: 'col', lg: 'row' }} align="start" justify="between" gap={8}>
<Box maxWidth="xl">
<Stack maxWidth="xl">
{/* Badge */}
<Box mb={4}>
<Stack mb={4}>
<Badge variant="primary" icon={Users}>
Team Racing
</Badge>
</Box>
</Stack>
<Heading level={1}>
{title}
@@ -67,15 +66,15 @@ export function TeamHeroSection({
<Stack direction="row" gap={3} wrap>
{actionsContent}
</Stack>
</Box>
</Stack>
{/* Side Content */}
<Box w={{ base: 'full', lg: '72' }}>
<Stack w={{ base: 'full', lg: '72' }}>
{sideContent}
</Box>
</Stack>
</Stack>
</Box>
</Box>
</Box>
</Stack>
</Stack>
</Stack>
);
}

View File

@@ -1,9 +1,8 @@
import React from 'react';
import { Users, UserPlus } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
import { Stack } from '@/ui/Stack';
interface TeamHeroStatsProps {
teamCount: number;
@@ -13,7 +12,7 @@ interface TeamHeroStatsProps {
export function TeamHeroStats({ teamCount, recruitingCount }: TeamHeroStatsProps) {
return (
<Stack direction="row" align="center" gap={4}>
<Box
<Stack
display="flex"
alignItems="center"
gap={2}
@@ -27,8 +26,8 @@ export function TeamHeroStats({ teamCount, recruitingCount }: TeamHeroStatsProps
<Icon icon={Users} size={4} color="text-purple-400" />
<Text weight="semibold" color="text-white">{teamCount}</Text>
<Text size="sm" color="text-gray-500">Teams</Text>
</Box>
<Box
</Stack>
<Stack
display="flex"
alignItems="center"
gap={2}
@@ -42,7 +41,7 @@ export function TeamHeroStats({ teamCount, recruitingCount }: TeamHeroStatsProps
<Icon icon={UserPlus} size={4} color="text-performance-green" />
<Text weight="semibold" color="text-white">{recruitingCount}</Text>
<Text size="sm" color="text-gray-500">Recruiting</Text>
</Box>
</Stack>
</Stack>
);
}

View File

@@ -1,5 +1,4 @@
import React from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Image } from '@/ui/Image';
@@ -14,7 +13,7 @@ interface TeamIdentityProps {
export function TeamIdentity({ name, logoUrl, performanceLevel, category }: TeamIdentityProps) {
return (
<Stack direction="row" align="center" gap={3}>
<Box width="10" height="10" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
<Stack width="10" height="10" rounded="lg" overflow="hidden" border borderColor="border-charcoal-outline">
<Image
src={logoUrl}
alt={name}
@@ -24,8 +23,8 @@ export function TeamIdentity({ name, logoUrl, performanceLevel, category }: Team
fullHeight
objectFit="cover"
/>
</Box>
<Box flex={1}>
</Stack>
<Stack flex={1}>
<Text weight="semibold" color="text-white" block truncate>{name}</Text>
{(performanceLevel || category) && (
<Stack direction="row" align="center" gap={2} mt={1} wrap>
@@ -34,13 +33,13 @@ export function TeamIdentity({ name, logoUrl, performanceLevel, category }: Team
)}
{category && (
<Stack direction="row" align="center" gap={1}>
<Box width="1.5" height="1.5" rounded="full" bg="bg-primary-blue" opacity={0.5} />
<Stack width="1.5" height="1.5" rounded="full" bg="bg-primary-blue" opacity={0.5} />
<Text size="xs" color="text-primary-blue">{category}</Text>
</Stack>
)}
</Stack>
)}
</Box>
</Stack>
</Stack>
);
}

View File

@@ -1,10 +1,9 @@
import { Crown, Trophy, Users } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Icon } from '@/ui/Icon';
import { Image } from '@/ui/Image';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
interface TeamLeaderboardItemProps {
@@ -37,7 +36,7 @@ export function TeamLeaderboardItem({
medalBorder,
}: TeamLeaderboardItemProps) {
return (
<Box
<Stack
as="button"
type="button"
onClick={onClick}
@@ -56,7 +55,7 @@ export function TeamLeaderboardItem({
className="last:border-0"
>
{/* Position */}
<Box
<Stack
w="8"
h="8"
display="flex"
@@ -75,10 +74,10 @@ export function TeamLeaderboardItem({
) : (
position
)}
</Box>
</Stack>
{/* Team Info */}
<Box w="9" h="9" rounded="md" overflow="hidden" bg="bg-deep-graphite" border style={{ borderColor: 'rgba(38, 38, 38, 0.8)' }} flexShrink={0}>
<Stack w="9" h="9" rounded="md" overflow="hidden" bg="bg-deep-graphite" border style={{ borderColor: 'rgba(38, 38, 38, 0.8)' }} flexShrink={0}>
<Image
src={logoUrl}
alt={name}
@@ -86,15 +85,15 @@ export function TeamLeaderboardItem({
height={36}
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
/>
</Box>
<Box style={{ flex: 1, minWidth: 0 }}>
</Stack>
<Stack style={{ flex: 1, minWidth: 0 }}>
<Text weight="medium" color="text-white" className="truncate" block>
{name}
</Text>
<Stack direction="row" align="center" gap={2} wrap mt={0.5}>
{category && (
<Stack direction="row" align="center" gap={1}>
<Box w="1.5" h="1.5" rounded="full" bg="bg-purple-500" />
<Stack w="1.5" h="1.5" rounded="full" bg="bg-purple-500" />
<Text size="xs" color="text-purple-400">{category}</Text>
</Stack>
)}
@@ -108,20 +107,20 @@ export function TeamLeaderboardItem({
</Stack>
{isRecruiting && (
<Stack direction="row" align="center" gap={1}>
<Box w="1.5" h="1.5" rounded="full" bg="bg-performance-green" />
<Stack w="1.5" h="1.5" rounded="full" bg="bg-performance-green" />
<Text size="xs" color="text-performance-green">Recruiting</Text>
</Stack>
)}
</Stack>
</Box>
</Stack>
{/* Rating */}
<Box textAlign="right">
<Stack textAlign="right">
<Text font="mono" weight="semibold" color="text-purple-400" block>
{typeof rating === 'number' ? Math.round(rating).toLocaleString() : '—'}
</Text>
<Text size="xs" color="text-gray-500">Rating</Text>
</Box>
</Box>
</Stack>
</Stack>
);
}

View File

@@ -1,5 +1,4 @@
import React from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Table, TableHead, TableBody, TableRow, TableHeader, TableCell } from '@/ui/Table';
@@ -21,7 +20,7 @@ interface TeamLeaderboardPanelProps {
export function TeamLeaderboardPanel({ teams, onTeamClick }: TeamLeaderboardPanelProps) {
return (
<Box border borderColor="border-steel-grey" bg="surface-charcoal/50" overflow="hidden">
<Stack border borderColor="border-steel-grey" bg="surface-charcoal/50" overflow="hidden">
<Table>
<TableHead className="bg-base-graphite/50">
<TableRow>
@@ -46,9 +45,9 @@ export function TeamLeaderboardPanel({ teams, onTeamClick }: TeamLeaderboardPane
</TableCell>
<TableCell>
<Stack direction="row" align="center" gap={3}>
<Box w="8" h="8" bg="base-graphite" border borderColor="border-steel-grey" display="flex" center overflow="hidden">
<Stack w="8" h="8" bg="base-graphite" border borderColor="border-steel-grey" display="flex" center overflow="hidden">
<TeamLogo teamId={team.id} alt={team.name} />
</Box>
</Stack>
<Text weight="bold" size="sm" color="text-white" className="group-hover:text-primary-blue transition-colors">
{team.name}
</Text>
@@ -70,6 +69,6 @@ export function TeamLeaderboardPanel({ teams, onTeamClick }: TeamLeaderboardPane
))}
</TableBody>
</Table>
</Box>
</Stack>
);
}

View File

@@ -1,7 +1,6 @@
'use client';
import React from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Button } from '@/ui/Button';
@@ -22,7 +21,7 @@ interface TeamMembersTableProps {
export function TeamMembersTable({ members, isAdmin, onRemoveMember }: TeamMembersTableProps) {
return (
<Box border borderColor="outline-steel" bg="surface-charcoal/30">
<Stack border borderColor="outline-steel" bg="surface-charcoal/30">
<Table>
<TableHead>
<TableRow>
@@ -38,16 +37,16 @@ export function TeamMembersTable({ members, isAdmin, onRemoveMember }: TeamMembe
<TableRow key={member.driverId}>
<TableCell>
<Stack direction="row" align="center" gap={3}>
<Box w="8" h="8" bg="base-black" border borderColor="outline-steel" display="flex" center>
<Stack w="8" h="8" bg="base-black" border borderColor="outline-steel" display="flex" center>
<Text size="xs" weight="bold" color="primary-accent">{member.driverName.substring(0, 2).toUpperCase()}</Text>
</Box>
</Stack>
<Text weight="bold" size="sm" color="text-white">{member.driverName}</Text>
</Stack>
</TableCell>
<TableCell>
<Box px={2} py={0.5} bg="base-black" border borderColor="outline-steel" display="inline-block">
<Stack px={2} py={0.5} bg="base-black" border borderColor="outline-steel" display="inline-block">
<Text size="xs" color="text-gray-400" font="mono" uppercase>{member.role}</Text>
</Box>
</Stack>
</TableCell>
<TableCell>
<Text size="xs" color="text-gray-500" font="mono">
@@ -74,6 +73,6 @@ export function TeamMembersTable({ members, isAdmin, onRemoveMember }: TeamMembe
))}
</TableBody>
</Table>
</Box>
</Stack>
);
}

View File

@@ -2,10 +2,9 @@
import { ChevronRight, Users } from 'lucide-react';
import { Badge } from '@/ui/Badge';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Icon } from '@/ui/Icon';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text';
@@ -44,7 +43,7 @@ export function TeamMembershipCard({
>
<Icon icon={Users} size={6} color="var(--neon-purple)" />
</Surface>
<Box style={{ flex: 1, minWidth: 0 }}>
<Stack style={{ flex: 1, minWidth: 0 }}>
<Text weight="semibold" color="text-white" className="truncate group-hover:text-purple-400 transition-colors" block>
{teamName}
</Text>
@@ -56,7 +55,7 @@ export function TeamMembershipCard({
Since {new Date(joinedAt).toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}
</Text>
</Stack>
</Box>
</Stack>
<Icon icon={ChevronRight} size={4} color="var(--text-gray-500)" className="group-hover:text-purple-400 transition-colors" />
</Surface>
</Link>

View File

@@ -1,11 +1,9 @@
import { Box } from '@/ui/Box';
import { Card } from '@/ui/Card';
import { Stack } from '@/ui/Stack';
import { Card , Card as Surface } from '@/ui/Card';
import { Heading } from '@/ui/Heading';
import { Link } from '@/ui/Link';
import { Stack } from '@/ui/Stack';
import { Surface } from '@/ui/Surface';
import { Text } from '@/ui/Text';
import { ChevronRight, Shield, Users } from 'lucide-react';
@@ -25,15 +23,15 @@ interface TeamMembershipGridProps {
export function TeamMembershipGrid({ memberships }: TeamMembershipGridProps) {
return (
<Card>
<Box mb={4}>
<Stack mb={4}>
<Heading level={2} icon={<Shield style={{ width: '1.25rem', height: '1.25rem', color: '#a855f7' }} />}>
Team Memberships
<Text size="sm" color="text-gray-500" weight="normal" style={{ marginLeft: '0.5rem' }}>({memberships.length})</Text>
</Heading>
</Box>
<Box style={{ display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: '1rem' }}>
</Stack>
<Stack style={{ display: 'grid', gridTemplateColumns: 'repeat(1, minmax(0, 1fr))', gap: '1rem' }}>
{memberships.map((membership) => (
<Box key={membership.team.id}>
<Stack key={membership.team.id}>
<Link
href={`/teams/${membership.team.id}`}
variant="ghost"
@@ -42,7 +40,7 @@ export function TeamMembershipGrid({ memberships }: TeamMembershipGridProps) {
<Surface variant="muted" rounded="lg" padding={3} style={{ backgroundColor: 'rgba(147, 51, 234, 0.2)', border: '1px solid rgba(147, 51, 234, 0.3)' }}>
<Users style={{ width: '1.5rem', height: '1.5rem', color: '#a855f7' }} />
</Surface>
<Box style={{ flex: 1, minWidth: 0 }}>
<Stack style={{ flex: 1, minWidth: 0 }}>
<Text weight="semibold" color="text-white" block truncate>{membership.team.name}</Text>
<Stack direction="row" align="center" gap={2} mt={1}>
<Surface variant="muted" rounded="full" padding={1} style={{ paddingLeft: '0.5rem', paddingRight: '0.5rem', backgroundColor: 'rgba(147, 51, 234, 0.2)', color: '#a855f7' }}>
@@ -50,13 +48,13 @@ export function TeamMembershipGrid({ memberships }: TeamMembershipGridProps) {
</Surface>
<Text size="xs" color="text-gray-500">Since {membership.joinedAt.toLocaleDateString('en-US', { month: 'short', year: 'numeric' })}</Text>
</Stack>
</Box>
</Stack>
<ChevronRight style={{ width: '1rem', height: '1rem', color: '#737373' }} />
</Surface>
</Link>
</Box>
</Stack>
))}
</Box>
</Stack>
</Card>
);
}

View File

@@ -2,7 +2,6 @@ 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 '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
@@ -75,7 +74,7 @@ export function TeamPodium({ teams, onClick }: TeamPodiumProps) {
p={0}
transition
>
<Box
<Stack
bg={getBgColor(position)}
rounded="xl"
border={true}
@@ -85,18 +84,18 @@ export function TeamPodium({ teams, onClick }: TeamPodiumProps) {
>
{/* Crown for 1st place */}
{position === 1 && (
<Box position="absolute" top="-4" left="1/2" translateX="-1/2">
<Box position="relative">
<Box animate="pulse">
<Stack position="absolute" top="-4" left="1/2" translateX="-1/2">
<Stack position="relative">
<Stack animate="pulse">
<Icon icon={Crown} size={8} color="text-warning-amber" />
</Box>
<Box position="absolute" inset="0" bg="bg-yellow-400" bgOpacity={0.3} blur="md" rounded="full" />
</Box>
</Box>
</Stack>
<Stack position="absolute" inset="0" bg="bg-yellow-400" bgOpacity={0.3} blur="md" rounded="full" />
</Stack>
</Stack>
)}
{/* Team logo */}
<Box h="20" w="20" display="flex" center rounded="xl" bg="bg-deep-graphite" border={true} borderColor="border-charcoal-outline" overflow="hidden" mb={3}>
<Stack h="20" w="20" display="flex" center rounded="xl" bg="bg-deep-graphite" border={true} borderColor="border-charcoal-outline" overflow="hidden" mb={3}>
<Image
src={team.logoUrl || getMediaUrl('team-logo', team.id)}
alt={team.name}
@@ -104,7 +103,7 @@ export function TeamPodium({ teams, onClick }: TeamPodiumProps) {
height={80}
objectFit="cover"
/>
</Box>
</Stack>
{/* Team name */}
<Text weight="bold" size="sm" color="text-white" align="center" block truncate maxWidth="28">
@@ -134,7 +133,7 @@ export function TeamPodium({ teams, onClick }: TeamPodiumProps) {
<Text size="xs" color="text-gray-400">{team.memberCount}</Text>
</Stack>
</Stack>
</Box>
</Stack>
</Button>
}
/>

View File

@@ -1,6 +1,5 @@
import React from 'react';
import { Users } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
@@ -43,9 +42,9 @@ export function TeamRankingsTable({ teams, sortBy, onTeamClick }: TeamRankingsTa
<Text size="xs" weight="medium" color="text-gray-500" block>Team</Text>
</TableHeader>
<TableHeader>
<Box display={{ base: 'none', lg: 'block' }}>
<Stack display={{ base: 'none', lg: 'block' }}>
<Text size="xs" weight="medium" color="text-gray-500" align="center" block>Members</Text>
</Box>
</Stack>
</TableHeader>
<TableHeader>
<Text size="xs" weight="medium" color="text-gray-500" align="center" block>Rating</Text>
@@ -74,26 +73,26 @@ export function TeamRankingsTable({ teams, sortBy, onTeamClick }: TeamRankingsTa
/>
</TableCell>
<TableCell>
<Box display={{ base: 'none', lg: 'flex' }} alignItems="center" justifyContent="center">
<Stack display={{ base: 'none', lg: 'flex' }} alignItems="center" justifyContent="center">
<Stack direction="row" align="center" gap={1.5}>
<Icon icon={Users} size={3.5} color="text-gray-500" />
<Text size="sm" color="text-gray-400">{team.memberCount}</Text>
</Stack>
</Box>
</Stack>
</TableCell>
<TableCell>
<Box display="flex" center>
<Stack display="flex" center>
<Text font="mono" weight="semibold" color={sortBy === 'rating' ? 'text-primary-blue' : 'text-white'}>
0
</Text>
</Box>
</Stack>
</TableCell>
<TableCell>
<Box display="flex" center>
<Stack display="flex" center>
<Text font="mono" weight="semibold" color={sortBy === 'wins' ? 'text-primary-blue' : 'text-white'}>
{team.totalWins}
</Text>
</Box>
</Stack>
</TableCell>
</TableRow>
))}

View File

@@ -4,7 +4,6 @@ import React, { useMemo, useState } from 'react';
import { Card } from '@/ui/Card';
import { useTeamRoster } from "@/hooks/team/useTeamRoster";
import type { DriverViewModel } from '@/lib/view-models/DriverViewModel';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Heading } from '@/ui/Heading';
@@ -76,9 +75,9 @@ export function TeamRoster({
if (loading) {
return (
<Card>
<Box display="flex" justifyContent="center" py={8}>
<Stack display="flex" justifyContent="center" py={8}>
<Text color="text-gray-400">Loading roster...</Text>
</Box>
</Stack>
</Card>
);
}
@@ -86,17 +85,17 @@ export function TeamRoster({
return (
<Card>
<Stack direction="row" align="center" justify="between" mb={6} wrap gap={4}>
<Box>
<Stack>
<Heading level={3}>Team Roster</Heading>
<Text size="sm" color="text-gray-400" block mt={1}>
{memberships.length} {memberships.length === 1 ? 'member' : 'members'} Avg Rating:{' '}
<Text color="text-primary-blue" weight="medium">{teamAverageRating.toFixed(0)}</Text>
</Text>
</Box>
</Stack>
<Stack direction="row" align="center" gap={2}>
<Text size="sm" color="text-gray-400">Sort by:</Text>
<Box width="32">
<Stack width="32">
<Select
value={sortBy}
onChange={(e) => setSortBy(e.target.value as typeof sortBy)}
@@ -106,7 +105,7 @@ export function TeamRoster({
{ value: 'name', label: 'Name' },
]}
/>
</Box>
</Stack>
</Stack>
</Stack>
@@ -130,7 +129,7 @@ export function TeamRoster({
overallRank={overallRank}
actions={canManageMembership ? (
<>
<Box width="32">
<Stack width="32">
<Select
value={displayRole}
onChange={(e) =>
@@ -141,7 +140,7 @@ export function TeamRoster({
{ value: 'admin', label: 'Admin' },
]}
/>
</Box>
</Stack>
<Button
variant="danger"

View File

@@ -1,5 +1,4 @@
import React, { ReactNode } from 'react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { DriverIdentity } from '@/components/drivers/DriverIdentity';
@@ -25,7 +24,7 @@ export function TeamRosterItem({
actions,
}: TeamRosterItemProps) {
return (
<Box
<Stack
bg="bg-iron-gray/50"
rounded="lg"
border={true}
@@ -47,17 +46,17 @@ export function TeamRosterItem({
{rating !== null && (
<Stack direction="row" align="center" gap={6}>
<Box display="flex" flexDirection="col" alignItems="center">
<Stack display="flex" flexDirection="col" alignItems="center">
<Text size="lg" weight="bold" color="text-primary-blue" block>
{rating}
</Text>
<Text size="xs" color="text-gray-400">Rating</Text>
</Box>
</Stack>
{overallRank !== null && (
<Box display="flex" flexDirection="col" alignItems="center">
<Stack display="flex" flexDirection="col" alignItems="center">
<Text size="sm" color="text-gray-300" block>#{overallRank}</Text>
<Text size="xs" color="text-gray-500">Rank</Text>
</Box>
</Stack>
)}
</Stack>
)}
@@ -68,6 +67,6 @@ export function TeamRosterItem({
</Stack>
)}
</Stack>
</Box>
</Stack>
);
}

View File

@@ -1,9 +1,8 @@
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Icon } from '@/ui/Icon';
import { Input } from '@/ui/Input';
import { Stack } from '@/ui/Stack';
import { Search } from 'lucide-react';
interface TeamSearchBarProps {
@@ -13,9 +12,9 @@ interface TeamSearchBarProps {
export function TeamSearchBar({ searchQuery, onSearchChange }: TeamSearchBarProps) {
return (
<Box id="teams-list" mb={6}>
<Stack id="teams-list" mb={6}>
<Stack direction="row" gap={4} wrap>
<Box flexGrow={1}>
<Stack flexGrow={1}>
<Input
type="text"
placeholder="Search teams by name, description, region, or language..."
@@ -23,8 +22,8 @@ export function TeamSearchBar({ searchQuery, onSearchChange }: TeamSearchBarProp
onChange={(e) => onSearchChange(e.target.value)}
icon={<Icon icon={Search} size={5} color="var(--text-gray-500)" />}
/>
</Box>
</Stack>
</Stack>
</Box>
</Stack>
);
}

View File

@@ -2,7 +2,6 @@
import React from 'react';
import { Plus } from 'lucide-react';
import { Box } from '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Heading } from '@/ui/Heading';
import { Text } from '@/ui/Text';
@@ -25,7 +24,7 @@ export function TeamsDirectoryHeader({ onCreateTeam }: TeamsDirectoryHeaderProps
borderColor="outline-steel"
pb={6}
>
<Box>
<Stack>
<Heading level={1} weight="bold">Teams</Heading>
<Text
color="text-gray-500"
@@ -37,8 +36,8 @@ export function TeamsDirectoryHeader({ onCreateTeam }: TeamsDirectoryHeaderProps
>
Operational Units & Racing Collectives
</Text>
</Box>
<Box>
</Stack>
<Stack>
<Button
variant="primary"
onClick={onCreateTeam}
@@ -46,7 +45,7 @@ export function TeamsDirectoryHeader({ onCreateTeam }: TeamsDirectoryHeaderProps
>
Initialize Team
</Button>
</Box>
</Stack>
</Stack>
);
}

View File

@@ -2,7 +2,6 @@ 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 '@/ui/Box';
import { Stack } from '@/ui/Stack';
import { Text } from '@/ui/Text';
import { Icon } from '@/ui/Icon';
@@ -75,7 +74,7 @@ export function TopThreePodium({ teams, onClick }: TopThreePodiumProps) {
p={0}
transition
>
<Box
<Stack
bg={getBgColor(position)}
rounded="xl"
border
@@ -85,18 +84,18 @@ export function TopThreePodium({ teams, onClick }: TopThreePodiumProps) {
>
{/* Crown for 1st place */}
{position === 1 && (
<Box position="absolute" top="-4" left="1/2" translateX="-1/2">
<Box position="relative">
<Box animate="pulse">
<Stack position="absolute" top="-4" left="1/2" translateX="-1/2">
<Stack position="relative">
<Stack animate="pulse">
<Icon icon={Crown} size={8} color="var(--warning-amber)" />
</Box>
<Box position="absolute" inset="0" bg="bg-yellow-400" bgOpacity={0.3} blur="md" rounded="full" />
</Box>
</Box>
</Stack>
<Stack position="absolute" inset="0" bg="bg-yellow-400" bgOpacity={0.3} blur="md" rounded="full" />
</Stack>
</Stack>
)}
{/* Team logo */}
<Box h="20" w="20" display="flex" center rounded="xl" bg="bg-deep-graphite" border borderColor="border-charcoal-outline" overflow="hidden" mb={3}>
<Stack h="20" w="20" display="flex" center rounded="xl" bg="bg-deep-graphite" border borderColor="border-charcoal-outline" overflow="hidden" mb={3}>
<Image
src={team.logoUrl || getMediaUrl('team-logo', team.id)}
alt={team.name}
@@ -104,7 +103,7 @@ export function TopThreePodium({ teams, onClick }: TopThreePodiumProps) {
height={80}
objectFit="cover"
/>
</Box>
</Stack>
{/* Team name */}
<Text weight="bold" size="sm" color="text-white" textAlign="center" block truncate maxWidth="28">
@@ -134,7 +133,7 @@ export function TopThreePodium({ teams, onClick }: TopThreePodiumProps) {
<Text size="xs" color="text-gray-400">{team.memberCount}</Text>
</Stack>
</Stack>
</Box>
</Stack>
</Button>
}
/>