From 5011cf5d1813d5f40437600ea4fc7df65798d138 Mon Sep 17 00:00:00 2001 From: Kalpesh Patel <1988.kalpesh@gmail.com> Date: Tue, 14 May 2024 12:26:06 +0530 Subject: [PATCH] Add text, icon and icon button support as prefix and suffix in text field. (#79) * Add text, icon and icon button support as prefix and suffix in text field. * Change scaffold's background color to surface so that we can see widgets on surface. --- example/lib/main.dart | 21 +++- lib/components/datepicker/date_picker.dart | 24 ++--- lib/components/textfield/text_field.dart | 108 +++++++++++++++++---- 3 files changed, 113 insertions(+), 40 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 20fed1b..6e6bd32 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -177,6 +177,7 @@ class _HomePageState extends State { Widget build(BuildContext context) { final theme = TUITheme.of(context); return Scaffold( + backgroundColor: theme.colors.surface, floatingActionButton: TUIFloatingActionButton( iconData: Symbol.map.value, onPressed: () {}, @@ -419,8 +420,8 @@ class _HomePageState extends State { const SizedBox(height: 8), const TUIInputField( labelText: "Label", - prefixIcon: Icon(TUISymbol.successCheckMark), - suffixIcon: Icon(TUISymbol.chevronDown), + prefix: TUITextFieldStartEndItem.icon(TUISymbol.successCheckMark), + suffix: TUITextFieldStartEndItem.icon(TUISymbol.chevronDown), helperText: "Helper / hint message goes here.", ), const SizedBox(height: 8), @@ -430,6 +431,22 @@ class _HomePageState extends State { errorText: "Error message goes here.", ), const SizedBox(height: 8), + TUIInputField( + labelText: null, + hintText: "Text Prefix and icon button Suffix", + prefix: const TUITextFieldStartEndItem.text("\$"), + suffix: TUITextFieldStartEndItem.iconButton( + icon: FluentIcons.dismiss_24_regular, + buttonType: TUIIconButtonType.ghost, + onButtonTap: () { + ScaffoldMessenger.of(context).showSnackBar(TUISnackBar( + context: context, + type: TUISnackBarType.information, + message: "Suffix icon clicked", + action: TUISnackBarAction.dismiss("Dismiss"), + )); + })), + const SizedBox(height: 8), Text("Chips", style: theme.typography.baseBold), const SizedBox(height: 8), TUIChip( diff --git a/lib/components/datepicker/date_picker.dart b/lib/components/datepicker/date_picker.dart index fdee36b..26cb1fa 100644 --- a/lib/components/datepicker/date_picker.dart +++ b/lib/components/datepicker/date_picker.dart @@ -12,16 +12,12 @@ class TUIDatePicker extends StatefulWidget { final String? labelText; final String? errorText; final String? helperText; - final String? prefixText; - final String? suffixText; + final TUITextFieldStartEndItem? prefix; + final TUITextFieldStartEndItem? suffix; final material.TextAlign textAlign; final material.TextAlignVertical? textAlignVertical; final material.TextCapitalization textCapitalization; final material.TextDirection? textDirection; - final material.Icon? prefixIcon; - final material.Color? prefixIconColor; - final material.Icon? suffixIcon; - final material.Color? suffixIconColor; final material.TextEditingController? controller; final DateFormat? format; final DateTime? minimumDate; @@ -41,16 +37,12 @@ class TUIDatePicker extends StatefulWidget { this.labelText, this.errorText, this.helperText, - this.prefixText, - this.suffixText, + this.prefix, + this.suffix, this.textAlign = material.TextAlign.start, this.textAlignVertical, this.textCapitalization = material.TextCapitalization.none, this.textDirection, - this.prefixIcon, - this.prefixIconColor, - this.suffixIcon, - this.suffixIconColor, this.controller, this.minimumDate, this.initialDate, @@ -97,16 +89,12 @@ class _TUIDatePickerState extends State { labelText: widget.labelText, errorText: widget.errorText, helperText: widget.helperText, - prefixText: widget.prefixText, - suffixText: widget.suffixText, + prefix: widget.prefix, + suffix: widget.suffix, textAlign: widget.textAlign, textAlignVertical: widget.textAlignVertical, textCapitalization: widget.textCapitalization, textDirection: widget.textDirection, - prefixIcon: widget.prefixIcon, - prefixIconColor: widget.prefixIconColor, - suffixIcon: widget.suffixIcon, - suffixIconColor: widget.suffixIconColor, controller: _dateController, onTap: () { _selectDate(context); diff --git a/lib/components/textfield/text_field.dart b/lib/components/textfield/text_field.dart index b40395f..2018d83 100644 --- a/lib/components/textfield/text_field.dart +++ b/lib/components/textfield/text_field.dart @@ -1,4 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:tarka_ui/components/button/icon_button.dart'; +import 'package:tarka_ui/components/button/style.dart'; import 'package:tarka_ui/styles/theme.dart'; /// TUIInputField is a text input field that allows users to enter text. @@ -28,8 +30,6 @@ class TUIInputField extends StatelessWidget { final String? labelText; final String? errorText; final String? helperText; - final String? prefixText; - final String? suffixText; final TextAlign textAlign; final TextAlignVertical? textAlignVertical; final TextCapitalization textCapitalization; @@ -38,10 +38,8 @@ class TUIInputField extends StatelessWidget { final int? minLines; final bool expands; final int? maxLength; - final Icon? prefixIcon; - final Color? prefixIconColor; - final Icon? suffixIcon; - final Color? suffixIconColor; + final TUITextFieldStartEndItem? prefix; + final TUITextFieldStartEndItem? suffix; final bool obscureText; final String obscuringCharacter; final TextEditingController? controller; @@ -63,8 +61,6 @@ class TUIInputField extends StatelessWidget { this.labelText = 'Label', this.errorText, this.helperText, - this.prefixText, - this.suffixText, this.textAlign = TextAlign.start, this.textAlignVertical = TextAlignVertical.center, this.textCapitalization = TextCapitalization.none, @@ -73,10 +69,8 @@ class TUIInputField extends StatelessWidget { this.minLines, this.expands = false, this.maxLength, - this.prefixIcon, - this.prefixIconColor, - this.suffixIcon, - this.suffixIconColor, + this.prefix, + this.suffix, this.obscureText = false, this.obscuringCharacter = '*', this.controller, @@ -108,8 +102,10 @@ class TUIInputField extends StatelessWidget { @override Widget build(BuildContext context) { final theme = TUITheme.of(context); - final suffixIconColor = this.suffixIconColor ?? theme.colors.inputText; - final prefixIconColor = this.prefixIconColor ?? theme.colors.inputText; + final (prefixIcon, prefixIconConstraints) = + _convertStartEndItemToWidget(prefix, theme); + final (suffixIcon, suffixIconConstraints) = + _convertStartEndItemToWidget(suffix, theme); return TextField( mouseCursor: mouseCursor, canRequestFocus: canRequestFocus, @@ -120,8 +116,10 @@ class TUIInputField extends StatelessWidget { keyboardType: keyboardType, textInputAction: textInputAction, controller: controller, + style: theme.typography.lg.copyWith(color: theme.colors.inputText), onTap: onTap, readOnly: readOnly, + expands: expands, enabled: enabled, obscureText: obscureText, obscuringCharacter: obscuringCharacter, @@ -141,12 +139,10 @@ class TUIInputField extends StatelessWidget { labelText: labelText, labelStyle: theme.typography.lg.copyWith(color: theme.colors.inputTextDim), - suffixText: suffixText, - prefixText: prefixText, - prefixIconColor: prefixIconColor, - prefixIcon: prefixIcon ?? prefixIcon, - suffixIconColor: suffixIconColor, - suffixIcon: suffixIcon ?? suffixIcon, + prefixIcon: prefixIcon, + prefixIconConstraints: prefixIconConstraints, + suffixIcon: suffixIcon, + suffixIconConstraints: suffixIconConstraints, errorText: errorText, helperText: helperText, errorStyle: @@ -173,4 +169,76 @@ class TUIInputField extends StatelessWidget { borderSide: BorderSide(color: theme.colors.error)), )); } + + (Widget?, BoxConstraints?) _convertStartEndItemToWidget( + TUITextFieldStartEndItem? item, TUIThemeData theme) { + if (item == null) { + return (null, null); + } + switch (item._type) { + case _StartEndItemType.text: + return ( + Align( + widthFactor: 1, + heightFactor: 1, + child: Text( + item.text!, + style: theme.typography.lg + .copyWith(color: theme.colors.inputTextDim), + ), + ), + null + ); + case _StartEndItemType.icon: + return ( + Icon( + item.icon!, + size: 24, + ), + null + ); + case _StartEndItemType.iconButton: + return ( + TUIIconButton( + type: item.buttonType!, + size: TUIIconButtonSize.px40, + onPressed: item.onButtonTap!, + iconData: item.icon!), + null + ); + } + } +} + +class TUITextFieldStartEndItem { + final IconData? icon; + final String? text; + final TUIIconButtonType? buttonType; + final VoidCallback? onButtonTap; + final _StartEndItemType _type; + + const TUITextFieldStartEndItem.text(this.text) + : icon = null, + buttonType = null, + onButtonTap = null, + _type = _StartEndItemType.text; + + const TUITextFieldStartEndItem.icon(this.icon) + : text = null, + buttonType = null, + onButtonTap = null, + _type = _StartEndItemType.icon; + + const TUITextFieldStartEndItem.iconButton( + {required this.icon, + required this.onButtonTap, + this.buttonType = TUIIconButtonType.ghost}) + : text = null, + _type = _StartEndItemType.iconButton; +} + +enum _StartEndItemType { + text, + icon, + iconButton; }