website refactor
This commit is contained in:
72
apps/website/ui/RaceRow.tsx
Normal file
72
apps/website/ui/RaceRow.tsx
Normal file
@@ -0,0 +1,72 @@
|
||||
import { ChevronRight } from 'lucide-react';
|
||||
import { ReactNode } from 'react';
|
||||
import { Box } from './Box';
|
||||
import { Surface } from './Surface';
|
||||
import { Icon } from './Icon';
|
||||
|
||||
export interface RaceRowProps {
|
||||
children: ReactNode;
|
||||
onClick: (e: React.MouseEvent) => void;
|
||||
status?: 'live' | 'upcoming' | 'past';
|
||||
emphasis?: 'low' | 'medium' | 'high';
|
||||
as?: any;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* RaceRow is a semantic UI component for displaying a race in a list.
|
||||
* It encapsulates the visual style of a race entry per the GridPilot theme.
|
||||
*/
|
||||
export const RaceRow = ({
|
||||
children,
|
||||
onClick,
|
||||
status = 'upcoming',
|
||||
emphasis = 'medium',
|
||||
as,
|
||||
href
|
||||
}: RaceRowProps) => {
|
||||
const isLive = status === 'live';
|
||||
|
||||
return (
|
||||
<Surface
|
||||
as={as}
|
||||
href={href}
|
||||
variant="precision"
|
||||
onClick={onClick}
|
||||
padding="none"
|
||||
cursor="pointer"
|
||||
position="relative"
|
||||
overflow="hidden"
|
||||
transition="all 0.2s ease-in-out"
|
||||
hoverBg="rgba(255, 255, 255, 0.02)"
|
||||
display="block"
|
||||
style={{ textDecoration: 'none', color: 'inherit' }}
|
||||
>
|
||||
{isLive && (
|
||||
<Box
|
||||
position="absolute"
|
||||
top={0}
|
||||
left={0}
|
||||
bottom={0}
|
||||
width="2px"
|
||||
bg="var(--ui-color-intent-success)"
|
||||
/>
|
||||
)}
|
||||
<Box
|
||||
display="flex"
|
||||
alignItems="center"
|
||||
gap={4}
|
||||
paddingX={4}
|
||||
paddingY={3}
|
||||
opacity={emphasis === 'low' ? 0.6 : 1}
|
||||
>
|
||||
<Box display="flex" alignItems="center" gap={4} flex={1}>
|
||||
{children}
|
||||
</Box>
|
||||
<Box flexShrink={0} display="flex" alignItems="center">
|
||||
<Icon icon={ChevronRight} size={4} intent="low" />
|
||||
</Box>
|
||||
</Box>
|
||||
</Surface>
|
||||
);
|
||||
};
|
||||
52
apps/website/ui/RaceRowCell.tsx
Normal file
52
apps/website/ui/RaceRowCell.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { Box } from './Box';
|
||||
import { Text } from './Text';
|
||||
|
||||
export interface RaceRowCellProps {
|
||||
children: ReactNode;
|
||||
label?: string;
|
||||
width?: string | number;
|
||||
align?: 'left' | 'center' | 'right';
|
||||
hideOnMobile?: boolean;
|
||||
}
|
||||
|
||||
export const RaceRowCell = ({
|
||||
children,
|
||||
label,
|
||||
width,
|
||||
align = 'left',
|
||||
hideOnMobile = false
|
||||
}: RaceRowCellProps) => {
|
||||
const alignmentClasses = {
|
||||
left: 'items-start text-left',
|
||||
center: 'items-center text-center',
|
||||
right: 'items-end text-right'
|
||||
}[align];
|
||||
|
||||
return (
|
||||
<Box
|
||||
display={hideOnMobile ? { base: 'none', md: 'flex' } : 'flex'}
|
||||
flexDirection="col"
|
||||
width={width}
|
||||
flexShrink={width ? 0 : 1}
|
||||
minWidth="0"
|
||||
className={alignmentClasses}
|
||||
>
|
||||
{label && (
|
||||
<Text
|
||||
size="xs"
|
||||
variant="low"
|
||||
uppercase
|
||||
weight="bold"
|
||||
letterSpacing="widest"
|
||||
marginBottom={0.5}
|
||||
>
|
||||
{label}
|
||||
</Text>
|
||||
)}
|
||||
<Box display="flex" alignItems="center" gap={2} minWidth="0" justifyContent={align === 'right' ? 'end' : (align === 'center' ? 'center' : 'start')}>
|
||||
{children}
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user