fix(#129): peaufiner le wizard famille (co-parent, hauteurs, à naître).

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-24 13:01:54 +02:00
co-authored by Cursor
parent cb5c1a5518
commit b4abb7d6de
2 changed files with 239 additions and 88 deletions
@@ -35,19 +35,23 @@ class ValidationFormMetrics {
);
static double get sectionTitleBlockHeight =>
sectionTitleFontSize + sectionTitleGapBelow;
sectionTitleFontSize * 1.25 + sectionTitleGapBelow;
/// Libellé : marge au-dessus de [fieldLabelFontSize] (métriques police).
static double get labeledRowHeight =>
fieldLabelFontSize + fieldLabelGapBelow + fieldHeight + rowGapBelow;
fieldLabelFontSize * 1.25 +
fieldLabelGapBelow +
fieldHeight +
rowGapBelow;
/// Corps modale AM : padding wizard + titre + [rows] lignes + nav.
/// Corps modale AM / famille : padding wizard + titre + [rows] lignes + nav.
static double shellBodyHeightForRows(int rows) =>
20 * 2 + // padding wizard
4 + // espace haut
sectionTitleBlockHeight +
rows * labeledRowHeight +
24 + // avant nav
44; // boutons
48; // boutons (+ marge anti-overflow)
}
/// Bloc type formulaire (titre de section + champs read-only) pour les modales de validation.
@@ -134,6 +138,7 @@ class ValidationFormGrid extends StatelessWidget {
label: f.label,
field: f.field,
expand: expandVertically,
labelTrailing: f.labelTrailing,
),
)
.toList();
@@ -262,28 +267,37 @@ class ValidationLabeledField extends StatelessWidget {
final String label;
final Widget field;
final bool expand;
/// Widget aligné à droite sur la ligne du libellé (ex. switch « Même adresse »).
final Widget? labelTrailing;
const ValidationLabeledField({
super.key,
required this.label,
required this.field,
this.expand = false,
this.labelTrailing,
});
@override
Widget build(BuildContext context) {
final labelStyle = TextStyle(
fontSize: ValidationFormMetrics.fieldLabelFontSize,
fontWeight: FontWeight.w500,
color: Colors.grey.shade700,
);
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: expand ? MainAxisSize.max : MainAxisSize.min,
children: [
Text(
label,
style: TextStyle(
fontSize: ValidationFormMetrics.fieldLabelFontSize,
fontWeight: FontWeight.w500,
color: Colors.grey.shade700,
if (labelTrailing == null)
Text(label, style: labelStyle)
else
Row(
children: [
Expanded(child: Text(label, style: labelStyle)),
labelTrailing!,
],
),
),
SizedBox(height: ValidationFormMetrics.fieldLabelGapBelow),
if (expand) Expanded(child: field) else field,
],
@@ -299,6 +313,7 @@ class ValidationEditableField extends StatelessWidget {
final String? hintText;
final int maxLines;
final bool compact;
final bool enabled;
const ValidationEditableField({
super.key,
@@ -308,6 +323,7 @@ class ValidationEditableField extends StatelessWidget {
this.hintText,
this.maxLines = 1,
this.compact = false,
this.enabled = true,
});
static const double _compactFieldHeight = 34;
@@ -339,6 +355,7 @@ class ValidationEditableField extends StatelessWidget {
if (maxLines > 1) {
return TextField(
controller: controller,
enabled: enabled,
keyboardType: keyboardType,
inputFormatters: inputFormatters,
maxLines: maxLines,
@@ -350,6 +367,7 @@ class ValidationEditableField extends StatelessWidget {
return _validationFieldFillHeight(
TextField(
controller: controller,
enabled: enabled,
keyboardType: keyboardType,
inputFormatters: inputFormatters,
maxLines: 1,
@@ -365,6 +383,7 @@ class ValidationEditableField extends StatelessWidget {
decoration: _compactDecoration(),
child: TextField(
controller: controller,
enabled: enabled,
keyboardType: keyboardType,
inputFormatters: inputFormatters,
maxLines: 1,
@@ -381,13 +400,15 @@ class ValidationEditableField extends StatelessWidget {
}
}
/// Étire le champ si le parent impose une hauteur (grille [expandVertically]).
/// Hauteur TF fixe ; en grille [expandVertically], étire jusqu’à la hauteur dispo.
Widget _validationFieldFillHeight(Widget field) {
return LayoutBuilder(
builder: (context, c) {
if (!c.hasBoundedHeight || !c.maxHeight.isFinite) return field;
final h = (c.hasBoundedHeight && c.maxHeight.isFinite)
? c.maxHeight
: ValidationFormMetrics.fieldHeight;
return SizedBox(
height: c.maxHeight,
height: h,
width: double.infinity,
child: field,
);
@@ -481,12 +502,14 @@ class ValidationPostalCodeField extends StatefulWidget {
final TextEditingController controller;
final String? hintText;
final bool allowEmpty;
final bool enabled;
const ValidationPostalCodeField({
super.key,
required this.controller,
this.hintText,
this.allowEmpty = false,
this.enabled = true,
});
@override
@@ -536,6 +559,7 @@ class _ValidationPostalCodeFieldState extends State<ValidationPostalCodeField> {
key: _fieldKey,
controller: widget.controller,
focusNode: _focusNode,
enabled: widget.enabled,
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
textAlignVertical: TextAlignVertical.center,