Normalize atoms: fix Card a11y + responsive padding, Input spacing

- Card: add Enter/Space keyboard activation for interactive cards (P1 a11y)
- Card: responsive padding — 16px mobile / 24px desktop (P1 responsive)
- Card: focus-visible outline uses focus token CSS var instead of palette
- Card: remove unused Theme import
- Input: convert raw px strings to MUI spacing (mb: 2.5, mt: 1.5)

Phase 1 retroactive review: atoms normalize + audit (Button 20/20,
Input 20/20, Card 18→20/20 after fixes)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-27 21:39:22 +11:00
parent 8a5a4dc128
commit 897d27aa54
2 changed files with 18 additions and 8 deletions

View File

@@ -2,7 +2,6 @@ import React from 'react';
import MuiCard from '@mui/material/Card';
import type { CardProps as MuiCardProps } from '@mui/material/Card';
import CardContent from '@mui/material/CardContent';
import type { Theme } from '@mui/material/styles';
// ─── Types ───────────────────────────────────────────────────────────────────
@@ -14,7 +13,7 @@ export interface CardProps extends Omit<MuiCardProps, 'raised' | 'variant'> {
interactive?: boolean;
/** Highlights the card as selected — brand border + warm background tint */
selected?: boolean;
/** Padding preset: "default" (24px), "compact" (16px), "none" (no wrapper) */
/** Padding preset: "default" (16px mobile / 24px desktop), "compact" (12px mobile / 16px desktop), "none" (no wrapper) */
padding?: 'default' | 'compact' | 'none';
/** Content to render inside the card */
children?: React.ReactNode;
@@ -58,7 +57,18 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
const muiVariant = variant === 'outlined' ? 'outlined' : undefined;
// Interactive cards need keyboard operability
const interactiveProps = interactive ? { tabIndex: 0 as const, role: 'button' as const } : {};
const handleKeyDown = interactive
? (e: React.KeyboardEvent<HTMLDivElement>) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
e.currentTarget.click();
}
}
: undefined;
const interactiveProps = interactive
? { tabIndex: 0 as const, role: 'button' as const, onKeyDown: handleKeyDown }
: {};
return (
<MuiCard
@@ -86,7 +96,7 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
// Focus-visible for keyboard accessibility on interactive cards
interactive && {
'&:focus-visible': {
outline: (theme: Theme) => `2px solid ${theme.palette.primary.main}`,
outline: '2px solid var(--fa-color-interactive-focus)',
outlineOffset: '2px',
},
},
@@ -97,9 +107,9 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
{padding !== 'none' ? (
<CardContent
sx={{
p: padding === 'compact' ? 4 : 6,
p: padding === 'compact' ? { xs: 3, md: 4 } : { xs: 4, md: 6 },
'&:last-child': {
pb: padding === 'compact' ? 4 : 6,
pb: padding === 'compact' ? { xs: 3, md: 4 } : { xs: 4, md: 6 },
},
}}
>

View File

@@ -104,7 +104,7 @@ export const Input = React.forwardRef<HTMLDivElement, InputProps>(
transform: 'none',
maxWidth: 'none',
pointerEvents: 'auto',
mb: '10px',
mb: 2.5,
// labelLg typography
fontFamily: (theme) => theme.typography.labelLg.fontFamily,
fontSize: (theme) => theme.typography.labelLg.fontSize,
@@ -163,7 +163,7 @@ export const Input = React.forwardRef<HTMLDivElement, InputProps>(
role={error ? 'alert' : undefined}
sx={{
mx: 0,
mt: '6px',
mt: 1.5,
// caption typography
fontFamily: (theme) => theme.typography.caption.fontFamily,
fontSize: (theme) => theme.typography.caption.fontSize,