Files
gridpilot.gg/apps/website/ui/LeaderboardRow.tsx
2026-01-20 23:50:29 +01:00

77 lines
1.8 KiB
TypeScript

import { ReactNode } from 'react';
import { Box } from './Box';
import { Surface } from './Surface';
import { Group } from './Group';
export interface LeaderboardRowProps {
rank: ReactNode;
identity: ReactNode;
stats: ReactNode;
onClick?: () => void;
}
/**
* LeaderboardRow is a semantic UI component for displaying an entry in a leaderboard.
* It follows the "Modern Precision" theme with obsessive detail.
*/
export const LeaderboardRow = ({
rank,
identity,
stats,
onClick
}: LeaderboardRowProps) => {
return (
<Surface
as={onClick ? 'button' : 'div'}
variant="precision"
onClick={onClick}
padding="none"
cursor={onClick ? 'pointer' : 'default'}
width="full"
textAlign="left"
transition="all 0.2s cubic-bezier(0.4, 0, 0.2, 1)"
hoverBg="rgba(25, 140, 255, 0.04)"
display="block"
style={{
border: 'none',
borderBottom: '1px solid var(--ui-color-border-muted)',
background: 'transparent',
position: 'relative'
}}
className="group"
>
<Box
display="flex"
alignItems="center"
gap={6}
paddingX={6}
paddingY={4}
className="transition-transform duration-200 group-hover:translate-x-1"
>
<Box width="10" display="flex" justifyContent="center" flexShrink={0}>
{rank}
</Box>
<Box flexGrow={1} minWidth="0">
{identity}
</Box>
<Group gap={8}>
{stats}
</Group>
</Box>
{/* Hover indicator */}
<Box
position="absolute"
left={0}
top={0}
bottom={0}
width={1}
bg="var(--ui-color-intent-primary)"
className="opacity-0 transition-opacity duration-200 group-hover:opacity-100"
/>
</Surface>
);
};