code quality
Some checks failed
CI / lint-typecheck (pull_request) Failing after 10s
CI / tests (pull_request) Has been skipped
CI / contract-tests (pull_request) Has been skipped
CI / e2e-tests (pull_request) Has been skipped
CI / comment-pr (pull_request) Has been skipped
CI / commit-types (pull_request) Has been skipped

This commit is contained in:
2026-01-27 17:36:39 +01:00
parent 9894c4a841
commit e04282d77e
32 changed files with 431 additions and 246 deletions

View File

@@ -9,14 +9,16 @@ export interface AvatarProps {
size?: 'sm' | 'md' | 'lg' | 'xl' | number;
fallback?: string;
className?: string;
'data-testid'?: string;
}
export const Avatar = ({
src,
alt,
export const Avatar = ({
src,
alt,
size = 'md',
fallback,
className
className,
'data-testid': dataTestId
}: AvatarProps) => {
const sizeMap: Record<string, string> = {
sm: '2rem',
@@ -36,9 +38,10 @@ export const Avatar = ({
const finalIconSize = typeof size === 'number' ? Math.round(size / 8) : iconSizeMap[size];
return (
<Surface
variant="muted"
rounded="full"
<Surface
data-testid={dataTestId}
variant="muted"
rounded="full"
className={className}
style={{
width: finalSize,

View File

@@ -14,6 +14,7 @@ export interface BadgeProps {
color?: string;
borderColor?: string;
transform?: 'none' | 'capitalize' | 'uppercase' | 'lowercase' | string;
'data-testid'?: string;
}
/** @internal */
@@ -31,7 +32,8 @@ export const Badge = ({
bg,
color,
borderColor,
transform
transform,
'data-testid': dataTestId
}: InternalBadgeProps) => {
const variantClasses = {
primary: 'bg-[var(--ui-color-intent-primary)] text-white',
@@ -76,7 +78,7 @@ export const Badge = ({
) : children;
return (
<Box as="span" className={classes} style={style}>
<Box data-testid={dataTestId} as="span" className={classes} style={style}>
{content}
</Box>
);

View File

@@ -237,6 +237,7 @@ export interface BoxProps<T extends ElementType> {
className?: string;
/** @deprecated DO NOT USE. Use semantic props instead. */
style?: React.CSSProperties;
'data-testid'?: string;
}
export const Box = forwardRef(<T extends ElementType = 'div'>(
@@ -394,7 +395,8 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
onPointerDown,
onPointerMove,
onPointerUp,
...props
'data-testid': dataTestId,
...props
}: BoxProps<T>,
ref: ForwardedRef<HTMLElement>
) => {
@@ -599,7 +601,8 @@ export const Box = forwardRef(<T extends ElementType = 'div'>(
onPointerDown={onPointerDown}
onPointerMove={onPointerMove}
onPointerUp={onPointerUp}
{...props}
data-testid={dataTestId}
{...props}
>
{children}
</Tag>

View File

@@ -10,6 +10,7 @@ export interface CardProps {
padding?: 'none' | 'sm' | 'md' | 'lg' | number;
onClick?: () => void;
fullHeight?: boolean;
'data-testid'?: string;
/** @deprecated Use semantic props instead. */
className?: string;
/** @deprecated Use semantic props instead. */
@@ -158,6 +159,7 @@ export const Card = forwardRef<HTMLDivElement, CardProps>(({
className={classes}
onClick={onClick}
style={Object.keys(style).length > 0 ? style : undefined}
data-testid={props['data-testid'] as string}
{...props}
>
{title && (

View File

@@ -9,6 +9,7 @@ export interface ContainerProps {
zIndex?: number;
/** @deprecated Use semantic props instead. */
py?: number;
'data-testid'?: string;
}
/**
@@ -23,6 +24,7 @@ export const Container = ({
position,
zIndex,
py,
'data-testid': dataTestId,
}: ContainerProps) => {
const sizeMap = {
sm: 'max-w-[40rem]',
@@ -54,7 +56,8 @@ export const Container = ({
};
return (
<div
<div
data-testid={dataTestId}
className={`mx-auto w-full ${sizeMap[size]} ${paddingMap[padding]} ${spacingMap[spacing]}`}
style={combinedStyle}
>

View File

@@ -15,14 +15,16 @@ export interface DriverIdentityProps {
contextLabel?: React.ReactNode;
meta?: React.ReactNode;
size?: 'sm' | 'md';
'data-testid'?: string;
}
export function DriverIdentity({ driver, href, contextLabel, meta, size = 'md' }: DriverIdentityProps) {
export function DriverIdentity({ driver, href, contextLabel, meta, size = 'md', 'data-testid': dataTestId }: DriverIdentityProps) {
const nameSize = size === 'sm' ? 'sm' : 'base';
const content = (
<Box display="flex" alignItems="center" gap={3} flexGrow={1} minWidth="0">
<Box data-testid={dataTestId} display="flex" alignItems="center" gap={3} flexGrow={1} minWidth="0">
<Avatar
data-testid="driver-avatar"
src={driver.avatarUrl || undefined}
alt={driver.name}
size={size === 'sm' ? 'sm' : 'md'}
@@ -30,7 +32,7 @@ export function DriverIdentity({ driver, href, contextLabel, meta, size = 'md' }
<Box flex={1} minWidth="0">
<Box display="flex" alignItems="center" gap={2} minWidth="0">
<Text size={nameSize as any} weight="medium" variant="high" truncate>
<Text data-testid="driver-name" size={nameSize as any} weight="medium" variant="high" truncate>
{driver.name}
</Text>
{contextLabel && (

View File

@@ -77,10 +77,10 @@ export function EmptyState({
) : null}
</Box>
<Heading level={3} weight="semibold">{title}</Heading>
<Heading data-testid="empty-state-title" level={3} weight="semibold">{title}</Heading>
{description && (
<Text variant="low" leading="relaxed">
<Text data-testid="empty-state-description" variant="low" leading="relaxed">
{description}
</Text>
)}

View File

@@ -36,6 +36,7 @@ export interface HeadingProps {
lineHeight?: string | number;
/** @deprecated Use semantic props instead. */
transition?: boolean;
'data-testid'?: string;
}
/**
@@ -65,6 +66,7 @@ export const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(({
groupHoverColor,
lineHeight,
transition,
'data-testid': dataTestId,
}, ref) => {
const Tag = `h${level}` as const;
@@ -128,7 +130,7 @@ export const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(({
};
return (
<Tag ref={ref} className={classes} style={Object.keys(combinedStyle).length > 0 ? combinedStyle : undefined} id={id}>
<Tag data-testid={dataTestId} ref={ref} className={classes} style={Object.keys(combinedStyle).length > 0 ? combinedStyle : undefined} id={id}>
<div className="flex items-center gap-2">
{icon}
{children}

View File

@@ -57,9 +57,10 @@ export const Input = forwardRef<HTMLInputElement, InputProps>(({
</Box>
)}
<Box
display="flex"
alignItems="center"
<Box
data-testid={testId ? `${testId}-container` : undefined}
display="flex"
alignItems="center"
gap={3}
paddingX={3}
height="9" // h-9

View File

@@ -40,7 +40,7 @@ export function PageHeader({
) : (
<Box width={1} height={8} backgroundColor="var(--ui-color-intent-primary)" />
)}
<Heading level={1} weight="bold" uppercase letterSpacing="tight">{title}</Heading>
<Heading data-testid="page-header-title" level={1} weight="bold" uppercase letterSpacing="tight">{title}</Heading>
</Stack>
{description && (
<Text variant="low" size="lg" uppercase mono letterSpacing="widest">

View File

@@ -8,15 +8,17 @@ export interface ProfileCardProps {
actions?: ReactNode;
variant?: 'default' | 'muted' | 'outline' | 'glass' | 'precision';
onClick?: () => void;
'data-testid'?: string;
}
export const ProfileCard = ({ identity, stats, actions, variant = 'default', onClick }: ProfileCardProps) => {
export const ProfileCard = ({ identity, stats, actions, variant = 'default', onClick, 'data-testid': dataTestId }: ProfileCardProps) => {
return (
<Card
variant={variant}
padding="md"
onClick={onClick}
<Card
variant={variant}
padding="md"
onClick={onClick}
fullHeight
data-testid={dataTestId as string}
>
<Box display="flex" justifyContent="between" alignItems="start" gap={4}>
<Box flex={1} minWidth="0">

View File

@@ -12,13 +12,15 @@ export interface SegmentedControlProps {
activeId: string;
onChange: (id: string) => void;
fullWidth?: boolean;
'data-testid'?: string;
}
export const SegmentedControl = ({
options,
activeId,
export const SegmentedControl = ({
options,
activeId,
onChange,
fullWidth = false
fullWidth = false,
'data-testid': dataTestId
}: SegmentedControlProps) => {
return (
<Surface
@@ -32,6 +34,7 @@ export const SegmentedControl = ({
const isSelected = option.id === activeId;
return (
<button
data-testid={dataTestId ? `${dataTestId}-${option.id}` : undefined}
key={option.id}
onClick={() => onChange(option.id)}
className={`flex-1 flex items-center justify-center gap-2 px-4 py-1.5 text-xs font-bold uppercase tracking-widest transition-all rounded-md ${

View File

@@ -26,10 +26,10 @@ export const StatBox = ({
<Icon icon={icon} size={5} intent={color ? undefined : intent} />
</Box>
<Box>
<Text size="xs" weight="bold" variant="low" uppercase>
<Text data-testid={`stat-label-${label.toLowerCase().replace(/\s+/g, '-')}`} size="xs" weight="bold" variant="low" uppercase>
{label}
</Text>
<Text size="xl" weight="bold" variant="high" block marginTop={0.5}>
<Text data-testid={`stat-value-${label.toLowerCase().replace(/\s+/g, '-')}`} size="xl" weight="bold" variant="high" block marginTop={0.5}>
{value}
</Text>
</Box>

View File

@@ -50,10 +50,10 @@ export const StatCard = ({
<Card variant={finalVariant} {...props}>
<Box display="flex" alignItems="start" justifyContent="between" marginBottom={4}>
<Box>
<Text size="xs" weight="bold" variant="low" uppercase>
<Text data-testid={`stat-label-${label.toLowerCase().replace(/\s+/g, '-')}`} size="xs" weight="bold" variant="low" uppercase>
{label}
</Text>
<Text size="2xl" weight="bold" variant={finalIntent as any || 'high'} font={font} block marginTop={1}>
<Text data-testid={`stat-value-${label.toLowerCase().replace(/\s+/g, '-')}`} size="2xl" weight="bold" variant={finalIntent as any || 'high'} font={font} block marginTop={1}>
{prefix}{value}{suffix}
</Text>
</Box>

View File

@@ -100,6 +100,7 @@ export interface TextProps {
hoverVariant?: string;
/** @deprecated Use semantic props instead. */
cursor?: string;
'data-testid'?: string;
}
/**
@@ -163,6 +164,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
capitalize,
hoverVariant,
cursor,
'data-testid': dataTestId,
}, ref) => {
const variantClasses = {
high: 'text-[var(--ui-color-text-high)]',
@@ -309,7 +311,7 @@ export const Text = forwardRef<HTMLElement, TextProps>(({
const Tag = as || 'p';
return (
<Tag ref={ref} className={classes} style={Object.keys(style).length > 0 ? style : undefined} id={id} htmlFor={htmlFor}>
<Tag data-testid={dataTestId} ref={ref} className={classes} style={Object.keys(style).length > 0 ? style : undefined} id={id} htmlFor={htmlFor}>
{children}
</Tag>
);