From d3bfa2dd6ab84b9dd2b2ad760d21dd3ef3ddb016 Mon Sep 17 00:00:00 2001 From: Richie Date: Wed, 25 Mar 2026 15:49:38 +1100 Subject: [PATCH] Fix Card selection layout shift and add transitions - Reserve 2px border on all cards (transparent for elevated, coloured for outlined) so selected state only changes colour, not width - Add 150ms ease-in-out transitions for border-color and background-color consistent with Button/Input interactive timing - Remove borderWidth/borderStyle from selected sx (now handled by theme) Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/atoms/Card/Card.tsx | 3 +-- src/theme/index.ts | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/components/atoms/Card/Card.tsx b/src/components/atoms/Card/Card.tsx index bcacf57..5e00b05 100644 --- a/src/components/atoms/Card/Card.tsx +++ b/src/components/atoms/Card/Card.tsx @@ -63,10 +63,9 @@ export const Card = React.forwardRef( elevation={0} sx={[ // Selected state: brand border + warm background + // Border width is always 2px (set in theme) — only colour changes here selected && { borderColor: 'var(--fa-card-border-selected)', - borderWidth: '2px', - borderStyle: 'solid', backgroundColor: 'var(--fa-card-background-selected)', }, // Interactive: hover fill + shadow lift + pointer diff --git a/src/theme/index.ts b/src/theme/index.ts index 5317abd..00b2489 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -479,7 +479,10 @@ export const theme = createTheme({ borderRadius: parseInt(t.CardBorderRadiusDefault, 10), backgroundColor: t.CardBackgroundDefault, boxShadow: t.CardShadowDefault, - transition: 'box-shadow 150ms ease-in-out', + // Reserve 2px border on ALL cards (transparent for elevated, coloured for outlined). + // Prevents layout shift when toggling selected state. + border: '2px solid transparent', + transition: 'box-shadow 150ms ease-in-out, border-color 150ms ease-in-out, background-color 150ms ease-in-out', }, }, variants: [