TF-4370 Add Description field to Create new Label modal
This commit is contained in:
@@ -26,6 +26,8 @@ class TextFieldBuilder extends StatefulWidget {
|
|||||||
final bool autocorrect;
|
final bool autocorrect;
|
||||||
final TextDirection textDirection;
|
final TextDirection textDirection;
|
||||||
final bool readOnly;
|
final bool readOnly;
|
||||||
|
final bool isFillContainer;
|
||||||
|
final TextAlignVertical? textAlignVertical;
|
||||||
final MouseCursor? mouseCursor;
|
final MouseCursor? mouseCursor;
|
||||||
final String? semanticLabel;
|
final String? semanticLabel;
|
||||||
|
|
||||||
@@ -36,6 +38,8 @@ class TextFieldBuilder extends StatefulWidget {
|
|||||||
this.obscureText = false,
|
this.obscureText = false,
|
||||||
this.autoFocus = false,
|
this.autoFocus = false,
|
||||||
this.readOnly = false,
|
this.readOnly = false,
|
||||||
|
this.isFillContainer = false,
|
||||||
|
this.textAlignVertical,
|
||||||
this.textStyle,
|
this.textStyle,
|
||||||
this.textDirection = TextDirection.ltr,
|
this.textDirection = TextDirection.ltr,
|
||||||
this.textInputAction,
|
this.textInputAction,
|
||||||
@@ -89,6 +93,8 @@ class _TextFieldBuilderState extends State<TextFieldBuilder> {
|
|||||||
decoration: widget.decoration,
|
decoration: widget.decoration,
|
||||||
maxLines: widget.maxLines,
|
maxLines: widget.maxLines,
|
||||||
minLines: widget.minLines,
|
minLines: widget.minLines,
|
||||||
|
textAlignVertical: widget.textAlignVertical,
|
||||||
|
expands: widget.isFillContainer,
|
||||||
keyboardAppearance: widget.keyboardAppearance,
|
keyboardAppearance: widget.keyboardAppearance,
|
||||||
style: widget.textStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
|
style: widget.textStyle ?? ThemeUtils.defaultTextStyleInterFont.copyWith(
|
||||||
color: AppColor.textFieldTextColor,
|
color: AppColor.textFieldTextColor,
|
||||||
|
|||||||
@@ -11,7 +11,12 @@ class DefaultInputFieldWidget extends StatelessWidget {
|
|||||||
final String? hintText;
|
final String? hintText;
|
||||||
final String? errorText;
|
final String? errorText;
|
||||||
final Color? inputColor;
|
final Color? inputColor;
|
||||||
|
final bool hasMaxLines;
|
||||||
|
final bool isFillContainer;
|
||||||
|
final TextAlignVertical? textAlignVertical;
|
||||||
|
final double? maxHeight;
|
||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
|
final TextInputAction? inputAction;
|
||||||
final OnTextChange? onTextChange;
|
final OnTextChange? onTextChange;
|
||||||
final OnTextSubmitted? onTextSubmitted;
|
final OnTextSubmitted? onTextSubmitted;
|
||||||
|
|
||||||
@@ -22,6 +27,11 @@ class DefaultInputFieldWidget extends StatelessWidget {
|
|||||||
this.errorText,
|
this.errorText,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
this.inputColor,
|
this.inputColor,
|
||||||
|
this.hasMaxLines = true,
|
||||||
|
this.isFillContainer = false,
|
||||||
|
this.textAlignVertical,
|
||||||
|
this.maxHeight,
|
||||||
|
this.inputAction,
|
||||||
this.onTextChange,
|
this.onTextChange,
|
||||||
this.onTextSubmitted,
|
this.onTextSubmitted,
|
||||||
});
|
});
|
||||||
@@ -30,17 +40,19 @@ class DefaultInputFieldWidget extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return TextFieldBuilder(
|
return TextFieldBuilder(
|
||||||
controller: textEditingController,
|
controller: textEditingController,
|
||||||
maxLines: 1,
|
maxLines: hasMaxLines ? 1 : null,
|
||||||
textInputAction: TextInputAction.next,
|
textInputAction: inputAction ?? TextInputAction.next,
|
||||||
textStyle: ThemeUtils.textStyleBodyBody3(
|
textStyle: ThemeUtils.textStyleBodyBody3(
|
||||||
color: inputColor ?? AppColor.m3SurfaceBackground,
|
color: inputColor ?? AppColor.m3SurfaceBackground,
|
||||||
),
|
),
|
||||||
|
isFillContainer: isFillContainer,
|
||||||
|
textAlignVertical: textAlignVertical,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
onTextSubmitted: onTextSubmitted,
|
onTextSubmitted: onTextSubmitted,
|
||||||
onTextChange: onTextChange,
|
onTextChange: onTextChange,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: errorText?.isNotEmpty == true ? 60 : 40,
|
maxHeight: maxHeight ?? (errorText?.isNotEmpty == true ? 60 : 40),
|
||||||
),
|
),
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: errorText?.isNotEmpty == true
|
fillColor: errorText?.isNotEmpty == true
|
||||||
|
|||||||
@@ -11,8 +11,13 @@ class LabelInputFieldBuilder extends StatelessWidget {
|
|||||||
final FocusNode? focusNode;
|
final FocusNode? focusNode;
|
||||||
final double? runSpacing;
|
final double? runSpacing;
|
||||||
final double? inputFieldMaxWidth;
|
final double? inputFieldMaxWidth;
|
||||||
|
final double? inputFieldHeight;
|
||||||
final bool arrangeHorizontally;
|
final bool arrangeHorizontally;
|
||||||
final bool isLabelHasColon;
|
final bool isLabelHasColon;
|
||||||
|
final bool hasMaxLines;
|
||||||
|
final bool isFillContainer;
|
||||||
|
final TextAlignVertical? textAlignVertical;
|
||||||
|
final TextInputAction? inputAction;
|
||||||
final OnTextChange? onTextChange;
|
final OnTextChange? onTextChange;
|
||||||
|
|
||||||
const LabelInputFieldBuilder({
|
const LabelInputFieldBuilder({
|
||||||
@@ -21,12 +26,17 @@ class LabelInputFieldBuilder extends StatelessWidget {
|
|||||||
required this.textEditingController,
|
required this.textEditingController,
|
||||||
this.arrangeHorizontally = true,
|
this.arrangeHorizontally = true,
|
||||||
this.isLabelHasColon = true,
|
this.isLabelHasColon = true,
|
||||||
|
this.hasMaxLines = true,
|
||||||
|
this.isFillContainer = false,
|
||||||
|
this.textAlignVertical,
|
||||||
this.hintText,
|
this.hintText,
|
||||||
this.errorText,
|
this.errorText,
|
||||||
this.focusNode,
|
this.focusNode,
|
||||||
this.labelStyle,
|
this.labelStyle,
|
||||||
this.runSpacing,
|
this.runSpacing,
|
||||||
this.inputFieldMaxWidth,
|
this.inputFieldMaxWidth,
|
||||||
|
this.inputFieldHeight,
|
||||||
|
this.inputAction,
|
||||||
this.onTextChange,
|
this.onTextChange,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -39,6 +49,11 @@ class LabelInputFieldBuilder extends StatelessWidget {
|
|||||||
hintText: hintText,
|
hintText: hintText,
|
||||||
errorText: errorText,
|
errorText: errorText,
|
||||||
focusNode: focusNode,
|
focusNode: focusNode,
|
||||||
|
hasMaxLines: hasMaxLines,
|
||||||
|
textAlignVertical: textAlignVertical,
|
||||||
|
isFillContainer: isFillContainer,
|
||||||
|
inputAction: inputAction,
|
||||||
|
maxHeight: inputFieldHeight,
|
||||||
onTextChange: onTextChange,
|
onTextChange: onTextChange,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -55,6 +55,9 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
final ValueNotifier<bool> _createLabelStateNotifier = ValueNotifier(false);
|
final ValueNotifier<bool> _createLabelStateNotifier = ValueNotifier(false);
|
||||||
final TextEditingController _nameInputController = TextEditingController();
|
final TextEditingController _nameInputController = TextEditingController();
|
||||||
final FocusNode _nameInputFocusNode = FocusNode();
|
final FocusNode _nameInputFocusNode = FocusNode();
|
||||||
|
final TextEditingController _descriptionInputController =
|
||||||
|
TextEditingController();
|
||||||
|
final FocusNode _descriptionInputFocusNode = FocusNode();
|
||||||
|
|
||||||
List<String> _labelDisplayNameList = <String>[];
|
List<String> _labelDisplayNameList = <String>[];
|
||||||
Color? _selectedColor;
|
Color? _selectedColor;
|
||||||
@@ -135,6 +138,12 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
_buildLabelNameInputField(appLocalizations),
|
_buildLabelNameInputField(appLocalizations),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 16),
|
||||||
|
child: _buildLabelDescriptionInputField(
|
||||||
|
appLocalizations,
|
||||||
|
),
|
||||||
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 26, bottom: 16),
|
padding: const EdgeInsets.only(top: 26, bottom: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -297,6 +306,29 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildLabelDescriptionInputField(AppLocalizations appLocalizations) {
|
||||||
|
return LabelInputFieldBuilder(
|
||||||
|
label: appLocalizations.labelDescription,
|
||||||
|
hintText: appLocalizations.labelDescriptionHintText,
|
||||||
|
textEditingController: _descriptionInputController,
|
||||||
|
focusNode: _descriptionInputFocusNode,
|
||||||
|
arrangeHorizontally: false,
|
||||||
|
isLabelHasColon: false,
|
||||||
|
hasMaxLines: false,
|
||||||
|
isFillContainer: true,
|
||||||
|
labelStyle: ThemeUtils.textStyleInter600().copyWith(
|
||||||
|
fontSize: 14,
|
||||||
|
height: 18 / 14,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
runSpacing: 16,
|
||||||
|
inputFieldMaxWidth: double.infinity,
|
||||||
|
inputFieldHeight: 84,
|
||||||
|
textAlignVertical: TextAlignVertical.top,
|
||||||
|
inputAction: TextInputAction.newline,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
void _onLabelNameInputChanged(
|
void _onLabelNameInputChanged(
|
||||||
AppLocalizations appLocalizations,
|
AppLocalizations appLocalizations,
|
||||||
String value,
|
String value,
|
||||||
@@ -376,6 +408,8 @@ class _CreateNewLabelModalState extends State<CreateNewLabelModal> {
|
|||||||
void dispose() {
|
void dispose() {
|
||||||
_nameInputFocusNode.dispose();
|
_nameInputFocusNode.dispose();
|
||||||
_nameInputController.dispose();
|
_nameInputController.dispose();
|
||||||
|
_descriptionInputFocusNode.dispose();
|
||||||
|
_descriptionInputController.dispose();
|
||||||
_labelNameErrorTextNotifier.dispose();
|
_labelNameErrorTextNotifier.dispose();
|
||||||
_labelSelectedColorNotifier.dispose();
|
_labelSelectedColorNotifier.dispose();
|
||||||
_createLabelStateNotifier.dispose();
|
_createLabelStateNotifier.dispose();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2026-03-04T11:35:04.572137",
|
"@@last_modified": "2026-03-11T14:39:59.601630",
|
||||||
"initializing_data": "Initializing data...",
|
"initializing_data": "Initializing data...",
|
||||||
"@initializing_data": {
|
"@initializing_data": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
@@ -5447,5 +5447,17 @@
|
|||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders_order": [],
|
"placeholders_order": [],
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"labelDescription": "Description (optional)",
|
||||||
|
"@labelDescription": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"labelDescriptionHintText": "Add a short description to explain what this label is for",
|
||||||
|
"@labelDescriptionHintText": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders_order": [],
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5762,4 +5762,18 @@ class AppLocalizations {
|
|||||||
name: 'deleteALabelFailure',
|
name: 'deleteALabelFailure',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String get labelDescription {
|
||||||
|
return Intl.message(
|
||||||
|
'Description (optional)',
|
||||||
|
name: 'labelDescription',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String get labelDescriptionHintText {
|
||||||
|
return Intl.message(
|
||||||
|
'Add a short description to explain what this label is for',
|
||||||
|
name: 'labelDescriptionHintText',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user