91ceca2be5
- tokens centralisés (Tint, IconSize, LineHeight, LetterSpacing), zéro hex en dur - accessibilité (rôles, labels, live regions, afficher/masquer mot de passe) - états vides/erreur complétés (ex. saisie introuvable), cibles tactiles >=44px - suppression du composant mort RepubliqueHeader Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
67 lines
1.7 KiB
TypeScript
67 lines
1.7 KiB
TypeScript
import {
|
|
Pressable,
|
|
StyleSheet,
|
|
View,
|
|
type AccessibilityRole,
|
|
type StyleProp,
|
|
type ViewStyle,
|
|
} from 'react-native';
|
|
import { Colors } from '@/lib/colors';
|
|
import { Radius, Shadow, Spacing } from '@/lib/theme';
|
|
|
|
interface CardProps {
|
|
children: React.ReactNode;
|
|
onPress?: () => void;
|
|
/** Padding interne (défaut lg = 16). Mettre 0 pour gérer soi-même. */
|
|
padding?: number;
|
|
/** Légère ombre portée. */
|
|
elevated?: boolean;
|
|
/** Libellé d'accessibilité (lecteurs d'écran), utile sur une carte cliquable. */
|
|
accessibilityLabel?: string;
|
|
/** Rôle d'accessibilité (défaut « button » si cliquable). */
|
|
accessibilityRole?: AccessibilityRole;
|
|
style?: StyleProp<ViewStyle>;
|
|
}
|
|
|
|
/** Conteneur DSFR : fond blanc, bordure grise fine, coins peu arrondis. */
|
|
export default function Card({
|
|
children,
|
|
onPress,
|
|
padding = Spacing.lg,
|
|
elevated = false,
|
|
accessibilityLabel,
|
|
accessibilityRole,
|
|
style,
|
|
}: CardProps) {
|
|
const content = [styles.card, { padding }, elevated && Shadow.card, style];
|
|
|
|
if (onPress) {
|
|
return (
|
|
<Pressable
|
|
onPress={onPress}
|
|
accessibilityRole={accessibilityRole ?? 'button'}
|
|
accessibilityLabel={accessibilityLabel}
|
|
style={({ pressed }) => [content, pressed && styles.pressed]}
|
|
>
|
|
{children}
|
|
</Pressable>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<View style={content} accessibilityRole={accessibilityRole} accessibilityLabel={accessibilityLabel}>
|
|
{children}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
const styles = StyleSheet.create({
|
|
card: {
|
|
backgroundColor: Colors.white,
|
|
borderWidth: 1,
|
|
borderColor: Colors.gray[200],
|
|
borderRadius: Radius.sm,
|
|
},
|
|
pressed: { backgroundColor: Colors.gray[50] },
|
|
});
|