Fix P1 accessibility issues in Button and Card
Button:
- Add aria-busy={loading} for assistive technology
- Add visually-hidden "Loading" text for screen readers
- Mark CircularProgress as aria-hidden (decorative)
Card:
- Add tabIndex={0} and role="button" when interactive
- Fix Record<string, any> → Theme type for type safety
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,7 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
variant={variant}
|
||||
size={size}
|
||||
disabled={loading || disabled}
|
||||
aria-busy={loading || undefined}
|
||||
sx={[
|
||||
underline &&
|
||||
variant === 'text' && {
|
||||
@@ -63,12 +64,30 @@ export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
>
|
||||
{children}
|
||||
{loading && (
|
||||
<>
|
||||
<CircularProgress
|
||||
size={16}
|
||||
color="inherit"
|
||||
thickness={3}
|
||||
aria-hidden
|
||||
sx={{ ml: 1 }}
|
||||
/>
|
||||
<span
|
||||
style={{
|
||||
position: 'absolute',
|
||||
width: 1,
|
||||
height: 1,
|
||||
padding: 0,
|
||||
margin: -1,
|
||||
overflow: 'hidden',
|
||||
clip: 'rect(0, 0, 0, 0)',
|
||||
whiteSpace: 'nowrap',
|
||||
borderWidth: 0,
|
||||
}}
|
||||
>
|
||||
Loading
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</MuiButton>
|
||||
);
|
||||
|
||||
@@ -2,6 +2,7 @@ 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 ───────────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -56,11 +57,17 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
||||
// Map FA variant names to MUI Card variant
|
||||
const muiVariant = variant === 'outlined' ? 'outlined' : undefined;
|
||||
|
||||
// Interactive cards need keyboard operability
|
||||
const interactiveProps = interactive
|
||||
? { tabIndex: 0 as const, role: 'button' as const }
|
||||
: {};
|
||||
|
||||
return (
|
||||
<MuiCard
|
||||
ref={ref}
|
||||
variant={muiVariant}
|
||||
elevation={0}
|
||||
{...interactiveProps}
|
||||
sx={[
|
||||
// Selected state: brand border + warm background
|
||||
// Border width is always 2px (set in theme) — only colour changes here
|
||||
@@ -81,7 +88,7 @@ export const Card = React.forwardRef<HTMLDivElement, CardProps>(
|
||||
// Focus-visible for keyboard accessibility on interactive cards
|
||||
interactive && {
|
||||
'&:focus-visible': {
|
||||
outline: (theme: Record<string, any>) =>
|
||||
outline: (theme: Theme) =>
|
||||
`2px solid ${theme.palette.primary.main}`,
|
||||
outlineOffset: '2px',
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user