website refactor

This commit is contained in:
2026-01-20 22:31:14 +01:00
parent 51288234f4
commit 7cbec00474
52 changed files with 577 additions and 146 deletions

View File

@@ -8,12 +8,17 @@ export interface BadgeProps {
children: ReactNode;
variant?: 'primary' | 'secondary' | 'success' | 'warning' | 'critical' | 'info' | 'outline' | 'default' | 'danger';
size?: 'xs' | 'sm' | 'md';
style?: React.CSSProperties;
icon?: LucideIcon;
rounded?: string;
bg?: string;
color?: string;
borderColor?: string;
transform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase' | string;
}
/** @internal */
interface InternalBadgeProps extends BadgeProps {
style?: React.CSSProperties;
}
export const Badge = ({
@@ -25,8 +30,9 @@ export const Badge = ({
rounded,
bg,
color,
borderColor
}: BadgeProps) => {
borderColor,
transform
}: InternalBadgeProps) => {
const variantClasses = {
primary: 'bg-[var(--ui-color-intent-primary)] text-white',
secondary: 'bg-[var(--ui-color-bg-surface)] text-[var(--ui-color-text-med)] border border-[var(--ui-color-border-default)]',
@@ -50,6 +56,8 @@ export const Badge = ({
variantClasses[variant],
sizeClasses[size],
rounded ? (rounded === 'full' ? 'rounded-full' : `rounded-${rounded}`) : 'rounded-none',
bg?.startsWith('bg-') ? bg : '',
color?.startsWith('text-') ? color : '',
].join(' ');
const style: React.CSSProperties = {
@@ -57,6 +65,7 @@ export const Badge = ({
...(bg ? { backgroundColor: bg.startsWith('bg-') ? undefined : bg } : {}),
...(color ? { color: color.startsWith('text-') ? undefined : color } : {}),
...(borderColor ? { borderColor: borderColor.startsWith('border-') ? undefined : borderColor, borderStyle: 'solid', borderWidth: '1px' } : {}),
...(transform ? { textTransform: transform as any } : {}),
};
const content = icon ? (

View File

@@ -120,8 +120,6 @@ export interface BoxProps<T extends ElementType> {
role?: React.AriaRole;
tabIndex?: number;
// Internal use only
style?: React.CSSProperties;
className?: string;
borderTop?: string | boolean;
borderBottom?: string | boolean;
borderLeft?: string | boolean;
@@ -140,6 +138,7 @@ export interface BoxProps<T extends ElementType> {
groupHoverWidth?: string;
animate?: any;
blur?: string;
backdropBlur?: string;
pointerEvents?: string;
bgOpacity?: number;
borderWidth?: string | number;
@@ -157,6 +156,10 @@ export interface BoxProps<T extends ElementType> {
translateX?: string;
translateY?: string;
translate?: string;
rotate?: string;
scale?: string | number;
perspective?: string | number;
whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-line' | 'pre-wrap';
cursor?: string;
fontSize?: string | ResponsiveValue<string>;
fontWeight?: string | number;
@@ -230,6 +233,10 @@ export interface BoxProps<T extends ElementType> {
onPointerDown?: React.PointerEventHandler<any>;
onPointerMove?: React.PointerEventHandler<any>;
onPointerUp?: React.PointerEventHandler<any>;
/** @deprecated DO NOT USE. Use semantic props instead. */
className?: string;
/** @deprecated DO NOT USE. Use semantic props instead. */
style?: React.CSSProperties;
}
export const Box = forwardRef(<T extends ElementType = 'div'>(
@@ -292,6 +299,7 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
groupHoverWidth,
animate,
blur,
backdropBlur,
pointerEvents,
bgOpacity,
borderWidth,
@@ -309,6 +317,10 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
translateX,
translateY,
translate,
rotate,
scale,
perspective,
whiteSpace,
cursor,
fontSize,
fontWeight,
@@ -483,11 +495,15 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
group ? 'group' : '',
animate === 'spin' ? 'animate-spin' : (animate === 'pulse' ? 'animate-pulse' : ''),
blur ? `blur-${blur}` : '',
backdropBlur ? `backdrop-blur-${backdropBlur}` : '',
pointerEvents ? `pointer-events-${pointerEvents}` : '',
hideScrollbar ? 'scrollbar-hide' : '',
truncate ? 'truncate' : '',
clickable ? 'cursor-pointer' : '',
lineClamp ? `line-clamp-${lineClamp}` : '',
(bg || backgroundColor)?.startsWith('bg-') ? (bg || backgroundColor) : '',
borderColor?.startsWith('border-') ? borderColor : '',
color?.startsWith('text-') ? color : '',
className
].filter(Boolean).join(' ');
@@ -521,6 +537,13 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
...(weight ? { fontWeight: weight } : {}),
...(shadow ? { boxShadow: shadow.startsWith('shadow-') ? undefined : shadow } : {}),
...(transform === true ? { transform: 'auto' } : (typeof transform === 'string' ? { transform } : {})),
...(translateX ? { translateX } : {}),
...(translateY ? { translateY } : {}),
...(translate ? { translate } : {}),
...(rotate ? { rotate } : {}),
...(scale ? { scale } : {}),
...(perspective ? { perspective } : {}),
...(whiteSpace ? { whiteSpace } : {}),
...(typeof fill === 'string' ? { fill } : (fill === true ? { fill: 'currentColor' } : {})),
...(stroke ? { stroke } : {}),
...(strokeWidth ? { strokeWidth } : {}),

View File

@@ -19,10 +19,8 @@ export const ControlBar = ({ children, leftContent }: ControlBarProps) => {
zIndex={100}
borderBottom={true}
backgroundColor="rgba(10, 10, 11, 0.92)"
className="backdrop-blur-xl"
style={{
boxShadow: '0 1px 0 0 rgba(255, 255, 255, 0.05), 0 10px 30px rgba(0, 0, 0, 0.35)',
}}
backdropBlur="xl"
shadow="0 1px 0 0 rgba(255, 255, 255, 0.05), 0 10px 30px rgba(0, 0, 0, 0.35)"
>
<Box display="flex" alignItems="center" justifyContent="between" h="full" width="full" px={4}>
{leftContent && (

View File

@@ -26,7 +26,16 @@ export const ErrorPageContainer = ({ children, size = 'md', variant = 'default'
position="relative"
overflow="hidden"
>
<Surface variant={variant} rounded="xl" padding={8} style={{ maxWidth: sizeMap[size], width: '100%', border: '1px solid var(--ui-color-border-default)', position: 'relative', zIndex: 10 }}>
<Surface
variant={variant}
rounded="xl"
padding={8}
maxWidth={sizeMap[size]}
width="100%"
border={true}
position="relative"
zIndex={10}
>
{children}
</Surface>
</Box>

View File

@@ -17,7 +17,7 @@ export const HorizontalStatItem = ({
return (
<Box display="flex" alignItems="center" justifyContent="between" paddingY={2}>
<Text size="sm" variant="low">{label}</Text>
<Text weight="semibold" variant={color ? undefined : intent} style={color ? { color } : undefined}>{value}</Text>
<Text weight="semibold" variant={color ? undefined : intent} color={color}>{value}</Text>
</Box>
);
};

View File

@@ -16,8 +16,8 @@ export const MiniStat = ({
}: MiniStatProps) => {
return (
<Box textAlign="center" padding={2} rounded="lg" bg="var(--ui-color-bg-surface-muted)">
<Text size="lg" weight="bold" variant={color ? undefined : intent} style={color ? { color } : undefined} block>{value}</Text>
<Text size="xs" variant="low" block style={{ fontSize: '10px' }}>{label}</Text>
<Text size="lg" weight="bold" variant={color ? undefined : intent} color={color} block>{value}</Text>
<Text size="xs" variant="low" block fontSize="10px">{label}</Text>
</Box>
);
};

View File

@@ -10,40 +10,44 @@ import { Surface } from './Surface';
import { Text } from './Text';
interface PageHeaderProps {
icon: LucideIcon;
title: string;
description?: string;
action?: React.ReactNode;
iconGradient?: string;
iconBorder?: string;
}
export function PageHeader({
icon,
title,
description,
action,
iconGradient = 'from-iron-gray to-deep-graphite',
iconBorder = 'border-charcoal-outline',
}: PageHeaderProps) {
return (
<Box mb={8}>
<Stack direction="row" align="center" justify="between" wrap gap={4}>
<Box>
<Stack direction="row" align="center" gap={4}>
<Surface variant="muted" rounded="xl" border padding={3} className={`bg-gradient-to-br ${iconGradient} ${iconBorder}`}>
<Icon icon={icon} size={7} color="#d1d5db" />
</Surface>
<Box>
<Heading level={1}>{title}</Heading>
{description && (
<Text color="text-gray-400" block mt={1}>{description}</Text>
)}
</Box>
</Stack>
<Box
marginBottom={12}
display="flex"
flexDirection={{ base: 'col', md: 'row' }}
alignItems={{ md: 'end' }}
justifyContent="space-between"
gap={6}
borderBottom="1px solid var(--ui-color-border-muted)"
paddingBottom={8}
>
<Box>
<Box display="flex" alignItems="center" gap={3} marginBottom={2}>
<Box width={1} height={8} backgroundColor="var(--ui-color-intent-primary)" />
<Heading level={1} weight="bold" uppercase>{title}</Heading>
</Box>
{action && <Box>{action}</Box>}
</Stack>
{description && (
<Text variant="low" size="lg" uppercase mono letterSpacing="0.2em">
{description}
</Text>
)}
</Box>
{action && (
<Box display="flex" alignItems="center">
{action}
</Box>
)}
</Box>
);
}

View File

@@ -15,7 +15,7 @@ export const RaceSummary = ({ track, meta, date }: RaceSummaryProps) => {
<Text size="xs" variant="low" block truncate>{meta}</Text>
</Box>
<Box textAlign="right">
<Text size="xs" variant="low" style={{ whiteSpace: 'nowrap' }}>
<Text size="xs" variant="low" whiteSpace="nowrap">
{date}
</Text>
</Box>

View File

@@ -8,6 +8,9 @@ export interface SectionProps {
id?: string;
minHeight?: string;
py?: number;
fullWidth?: boolean;
maxWidth?: string;
/** @deprecated DO NOT USE. Use semantic props instead. */
className?: string;
}
@@ -18,7 +21,9 @@ export const Section = ({
id,
minHeight,
py,
className
className,
fullWidth = false,
maxWidth = '80rem'
}: SectionProps) => {
const variantClasses = {
default: 'bg-[var(--ui-color-bg-base)]',
@@ -44,9 +49,13 @@ export const Section = ({
...(minHeight ? { minHeight } : {}),
...(py !== undefined ? { paddingTop: `${py * 0.25}rem`, paddingBottom: `${py * 0.25}rem` } : {})
}}>
<Box marginX="auto" maxWidth="80rem" paddingX={4}>
{children}
</Box>
{fullWidth ? (
children
) : (
<Box marginX="auto" maxWidth={maxWidth} paddingX={4}>
{children}
</Box>
)}
</section>
);
};

View File

@@ -15,8 +15,6 @@ export interface TextProps {
leading?: 'none' | 'tight' | 'snug' | 'normal' | 'relaxed' | 'loose' | any;
block?: boolean;
truncate?: boolean;
className?: string;
style?: CSSProperties;
mt?: number | any;
mb?: number | any;
ml?: number | any;
@@ -33,6 +31,9 @@ export interface TextProps {
display?: string | ResponsiveValue<string | any>;
opacity?: number;
maxWidth?: string | number;
maxHeight?: string | number;
overflow?: string;
whiteSpace?: 'normal' | 'nowrap' | 'pre' | 'pre-line' | 'pre-wrap';
mx?: string | number;
pl?: number;
px?: number;
@@ -55,8 +56,13 @@ export interface TextProps {
gap?: number;
cursor?: string;
width?: string | number;
height?: string | number;
htmlFor?: string;
transform?: string;
transform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase' | string;
/** @deprecated DO NOT USE. Use semantic props instead. */
className?: string;
/** @deprecated DO NOT USE. Use semantic props instead. */
style?: CSSProperties;
}
/**
@@ -93,6 +99,9 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
display,
opacity,
maxWidth,
maxHeight,
overflow,
whiteSpace,
mx,
pl,
px,
@@ -115,6 +124,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
gap,
cursor,
width,
height,
htmlFor,
transform,
}, ref) => {
@@ -200,6 +210,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
italic ? 'italic' : '',
animate === 'pulse' ? 'animate-pulse' : '',
capitalize ? 'capitalize' : '',
color?.startsWith('text-') ? color : '',
className,
].filter(Boolean).join(' ');
@@ -210,8 +221,12 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
...(gap !== undefined ? { gap: `${gap * 0.25}rem` } : {}),
...(cursor ? { cursor } : {}),
...(width !== undefined ? { width } : {}),
...(height !== undefined ? { height } : {}),
...(opacity !== undefined ? { opacity } : {}),
...(maxWidth !== undefined ? { maxWidth } : {}),
...(maxHeight !== undefined ? { maxHeight } : {}),
...(overflow !== undefined ? { overflow } : {}),
...(whiteSpace !== undefined ? { whiteSpace } : {}),
...(mx === 'auto' ? { marginLeft: 'auto', marginRight: 'auto' } : {}),
...(pl !== undefined ? { paddingLeft: `${pl * 0.25}rem` } : {}),
...(px !== undefined ? { paddingLeft: `${px * 0.25}rem`, paddingRight: `${px * 0.25}rem` } : {}),
@@ -224,7 +239,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
...(mr !== undefined ? { marginRight: typeof mr === 'number' ? `${mr * 0.25}rem` : mr } : {}),
...(marginTop !== undefined ? { marginTop: typeof marginTop === 'number' ? `${marginTop * 0.25}rem` : marginTop } : {}),
...(marginBottom !== undefined ? { marginBottom: typeof marginBottom === 'number' ? `${marginBottom * 0.25}rem` : marginBottom } : {}),
...(color ? { color } : {}),
...(color ? { color: color.startsWith('text-') ? undefined : color } : {}),
...(letterSpacing ? { letterSpacing } : {}),
...(lineHeight ? { lineHeight } : {}),
...(flexGrow !== undefined ? { flexGrow } : {}),

View File

@@ -35,17 +35,15 @@ export const Toast = ({
return (
<Box
style={{
transform: isVisible && !isExiting ? 'translateX(0)' : 'translateX(100%)',
opacity: isVisible && !isExiting ? 1 : 0,
transition: 'all 0.3s ease-in-out',
width: '24rem'
}}
translateX={isVisible && !isExiting ? '0' : '100%'}
opacity={isVisible && !isExiting ? 1 : 0}
transition="all 0.3s ease-in-out"
width="24rem"
>
<Surface variant="muted" rounded="xl" shadow="xl" style={{ border: `1px solid ${intentColors[intent]}33`, overflow: 'hidden' }}>
<Surface variant="muted" rounded="xl" shadow="xl" borderColor={`${intentColors[intent]}33`} border={true} overflow="hidden">
{progress !== undefined && (
<Box height="1px" bg="rgba(255,255,255,0.1)">
<Box height="100%" bg={intentColors[intent]} style={{ width: `${progress}%`, transition: 'width 0.1s linear' }} />
<Box height="100%" bg={intentColors[intent]} width={`${progress}%`} transition="width 0.1s linear" />
</Box>
)}
<Box padding={4} display="flex" gap={3}>