159 lines
3.7 KiB
Dart
159 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
import '../../unionflow_design_system.dart';
|
|
|
|
/// Card standardisé UnionFlow
|
|
///
|
|
/// Composant Card unifié avec 3 styles prédéfinis :
|
|
/// - elevated : Card avec ombre (par défaut)
|
|
/// - outlined : Card avec bordure
|
|
/// - filled : Card avec fond coloré
|
|
///
|
|
/// Usage:
|
|
/// ```dart
|
|
/// UFCard(
|
|
/// child: Text('Contenu'),
|
|
/// )
|
|
///
|
|
/// UFCard.outlined(
|
|
/// child: Text('Contenu'),
|
|
/// )
|
|
///
|
|
/// UFCard.filled(
|
|
/// color: ColorTokens.primary,
|
|
/// child: Text('Contenu'),
|
|
/// )
|
|
/// ```
|
|
class UFCard extends StatelessWidget {
|
|
final Widget child;
|
|
final EdgeInsets? padding;
|
|
final EdgeInsets? margin;
|
|
final VoidCallback? onTap;
|
|
final VoidCallback? onLongPress;
|
|
final UFCardStyle style;
|
|
final Color? color;
|
|
final Color? borderColor;
|
|
final double? borderWidth;
|
|
final double? elevation;
|
|
final double? borderRadius;
|
|
|
|
/// Card avec ombre (style par défaut)
|
|
const UFCard({
|
|
super.key,
|
|
required this.child,
|
|
this.padding,
|
|
this.margin,
|
|
this.onTap,
|
|
this.onLongPress,
|
|
this.color,
|
|
this.elevation,
|
|
this.borderRadius,
|
|
}) : style = UFCardStyle.elevated,
|
|
borderColor = null,
|
|
borderWidth = null;
|
|
|
|
/// Card avec bordure
|
|
const UFCard.outlined({
|
|
super.key,
|
|
required this.child,
|
|
this.padding,
|
|
this.margin,
|
|
this.onTap,
|
|
this.onLongPress,
|
|
this.color,
|
|
this.borderColor,
|
|
this.borderWidth,
|
|
this.borderRadius,
|
|
}) : style = UFCardStyle.outlined,
|
|
elevation = null;
|
|
|
|
/// Card avec fond coloré
|
|
const UFCard.filled({
|
|
super.key,
|
|
required this.child,
|
|
this.padding,
|
|
this.margin,
|
|
this.onTap,
|
|
this.onLongPress,
|
|
required this.color,
|
|
this.borderRadius,
|
|
}) : style = UFCardStyle.filled,
|
|
borderColor = null,
|
|
borderWidth = null,
|
|
elevation = null;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final effectivePadding = padding ?? const EdgeInsets.all(SpacingTokens.cardPadding);
|
|
final effectiveMargin = margin ?? EdgeInsets.zero;
|
|
final effectiveBorderRadius = borderRadius ?? SpacingTokens.radiusLg;
|
|
|
|
Widget content = Container(
|
|
padding: effectivePadding,
|
|
decoration: _getDecoration(effectiveBorderRadius),
|
|
child: child,
|
|
);
|
|
|
|
if (onTap != null || onLongPress != null) {
|
|
content = InkWell(
|
|
onTap: onTap,
|
|
onLongPress: onLongPress,
|
|
borderRadius: BorderRadius.circular(effectiveBorderRadius),
|
|
child: content,
|
|
);
|
|
}
|
|
|
|
return Container(
|
|
margin: effectiveMargin,
|
|
child: content,
|
|
);
|
|
}
|
|
|
|
BoxDecoration _getDecoration(double radius) {
|
|
switch (style) {
|
|
case UFCardStyle.elevated:
|
|
return BoxDecoration(
|
|
color: color ?? ColorTokens.surface,
|
|
borderRadius: BorderRadius.circular(radius),
|
|
boxShadow: elevation != null
|
|
? [
|
|
BoxShadow(
|
|
color: ColorTokens.shadow,
|
|
blurRadius: elevation!,
|
|
offset: const Offset(0, 2),
|
|
),
|
|
]
|
|
: ShadowTokens.sm,
|
|
);
|
|
|
|
case UFCardStyle.outlined:
|
|
return BoxDecoration(
|
|
color: color ?? ColorTokens.surface,
|
|
borderRadius: BorderRadius.circular(radius),
|
|
border: Border.all(
|
|
color: borderColor ?? ColorTokens.outline,
|
|
width: borderWidth ?? 1.0,
|
|
),
|
|
);
|
|
|
|
case UFCardStyle.filled:
|
|
return BoxDecoration(
|
|
color: color ?? ColorTokens.surfaceContainer,
|
|
borderRadius: BorderRadius.circular(radius),
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Styles de Card disponibles
|
|
enum UFCardStyle {
|
|
/// Card avec ombre
|
|
elevated,
|
|
|
|
/// Card avec bordure
|
|
outlined,
|
|
|
|
/// Card avec fond coloré
|
|
filled,
|
|
}
|
|
|