πŸ“ Flutter Form Kit

A comprehensive Flutter package for beautiful, cross-platform form input widgets with consistent styling and validation support.

pub package License: MIT

✨ Features

  • πŸ“± Cross-platform: Native iOS/macOS and Material Design styling
  • 🎨 Customizable: Extensive styling options for all components
  • βœ… Validation: Built-in form validation support
  • β™Ώ Accessible: Proper focus handling and keyboard navigation
  • 🌍 Localizable: Full localization support
  • πŸ”§ Flexible: Easy to integrate with existing form systems
  • ⚑ Performance: Optimized for smooth animations and interactions

πŸ“¦ Installation

Add this to your package's pubspec.yaml file:

dependencies:
  flutter_form_kit: ^1.0.0

Then run:

flutter pub get

πŸš€ Quick Start

import 'package:flutter_form_kit/flutter_form_kit.dart';

// Basic text field
CustomTextFormField(
  hintText: 'Enter your name',
  label: 'Full Name',
  textInputType: TextInputType.text,
  validator: (value) => value?.isEmpty == true ? 'Required' : null,
)

// Password field with visibility toggle
CustomPasswordField(
  hintText: 'Enter password',
  label: 'Password',
  validator: (value) => value?.length < 6 ? 'Too short' : null,
)

// Dropdown selection
CustomDropdownFormField<String>(
  value: selectedValue,
  items: ['Option 1', 'Option 2', 'Option 3'],
  hintText: 'Select an option',
  onChanged: (value) => setState(() => selectedValue = value),
)

πŸ“– Components

CustomTextFormField

A cross-platform text input field with consistent styling.

CustomTextFormField(
  hintText: 'Enter your email',
  label: 'Email Address',
  textInputType: TextInputType.emailAddress,
  validator: (value) {
    if (value?.isEmpty == true) return 'Email is required';
    if (!value!.contains('@')) return 'Invalid email';
    return null;
  },
  onChanged: (value) => print('Email: $value'),
  // Styling options
  borderRadius: 12.0,
  borderColor: Colors.grey,
  fillColor: Colors.white,
  textStyle: TextStyle(fontSize: 16),
)

CustomPasswordField

A password field with built-in visibility toggle.

CustomPasswordField(
  hintText: 'Enter password',
  label: 'Password',
  validator: (value) {
    if (value?.isEmpty == true) return 'Password is required';
    if (value!.length < 8) return 'Password too short';
    return null;
  },
  // Custom icons
  showPasswordIcon: Icons.visibility,
  hidePasswordIcon: Icons.visibility_off,
  iconColor: Colors.grey,
)

CustomDropdownFormField

A cross-platform dropdown with search functionality.

CustomDropdownFormField<String>(
  value: selectedCountry,
  items: countries,
  hintText: 'Select country',
  label: 'Country',
  onChanged: (value) => setState(() => selectedCountry = value),
  // Search functionality
  enableSearch: true,
  searchHint: 'Search countries...',
  // Custom item builder
  itemBuilder: (context, item, isSelected) => ListTile(
    title: Text(item),
    trailing: isSelected ? Icon(Icons.check) : null,
  ),
)

CustomButton

A cross-platform button with loading states and icons.

CustomButton(
  text: 'Submit',
  onPressed: () => handleSubmit(),
  // Styling
  backgroundColor: Colors.blue,
  borderRadius: 12.0,
  padding: EdgeInsets.symmetric(vertical: 16),
  // Icons
  prefixIcon: Icon(Icons.send),
  // Loading state
  isLoading: isSubmitting,
  loadingIndicatorColor: Colors.white,
)

CustomCheckBox

A customizable checkbox with animations.

CustomCheckBox(
  isChecked: isAgreed,
  onChecked: (value) => setState(() => isAgreed = value),
  size: 24,
  borderRadius: 6,
  checkColor: Colors.white,
  fillColor: Colors.blue,
  animationDuration: Duration(milliseconds: 200),
)

CustomRadioCheckBox

A radio-style checkbox with label.

CustomRadioCheckBox(
  value: isSelected,
  onChanged: (value) => setState(() => isSelected = value),
  label: 'I agree to terms and conditions',
  size: 20,
  activeColor: Colors.blue,
  spacing: 12,
  labelStyle: TextStyle(fontSize: 16),
)

πŸŽ›οΈ Configuration Options

Common Styling Properties

Property Type Default Description
borderRadius double 12.0 Corner radius
borderWidth double 1.2 Border width
focusedBorderWidth double 1.8 Focused border width
fillColor Color? Colors.white Background color
textColor Color? Colors.black87 Text color
borderColor Color? Colors.grey Border color
errorBorderColor Color Colors.red Error border color

Text Styling

Property Type Default Description
textStyle TextStyle? null Input text style
labelStyle TextStyle? null Label text style
hintStyle TextStyle? null Hint text style
errorStyle TextStyle? null Error text style

🌍 Localization

All text properties support localization:

CustomTextFormField(
  hintText: S.of(context).emailHint,
  label: S.of(context).emailLabel,
  validator: (value) => value?.isEmpty == true 
      ? S.of(context).emailRequired 
      : null,
)

πŸ“± Platform Behavior

iOS/macOS

  • Uses CupertinoTextField for native iOS styling
  • Uses CupertinoPicker for dropdowns
  • Uses CupertinoButton for buttons

Android/Other Platforms

  • Uses TextFormField with Material Design styling
  • Uses showModalBottomSheet for dropdowns
  • Uses Material and InkWell for buttons

πŸ§ͺ Testing

The package includes comprehensive tests. Run them with:

flutter test

🎨 Customization Examples

Custom Theme

// Create a custom theme
class MyFormTheme {
  static const primaryColor = Color(0xFF6366F1);
  static const borderRadius = 16.0;
  static const spacing = 20.0;
  
  static CustomTextFormField styledTextField({
    required String hintText,
    required String? Function(String?) validator,
  }) {
    return CustomTextFormField(
      hintText: hintText,
      validator: validator,
      borderRadius: borderRadius,
      borderColor: primaryColor.withOpacity(0.3),
      focusedBorderColor: primaryColor,
      fillColor: Colors.grey.shade50,
    );
  }
}

Form Builder Pattern

class LoginForm extends StatefulWidget {
  @override
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<LoginForm> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  
  @override
  Widget build(BuildContext context) {
    return Form(
      key: _formKey,
      child: Column(
        children: [
          CustomTextFormField(
            controller: _emailController,
            hintText: 'Email',
            textInputType: TextInputType.emailAddress,
            validator: (value) => value?.isEmpty == true ? 'Required' : null,
          ),
          SizedBox(height: 16),
          CustomPasswordField(
            controller: _passwordController,
            hintText: 'Password',
            validator: (value) => value?.length < 6 ? 'Too short' : null,
          ),
          SizedBox(height: 24),
          CustomButton(
            text: 'Login',
            onPressed: _handleLogin,
            isLoading: _isLoading,
          ),
        ],
      ),
    );
  }
}

🀝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ™ Acknowledgments

  • Flutter team for the amazing framework
  • Contributors and users who provide feedback

πŸ“ž Support

If you encounter any problems or have suggestions, please file an issue at the GitHub repository.


Made with ❀️ for the Flutter community

Libraries

form_kit_flutter
A comprehensive Flutter package for beautiful, cross-platform form input widgets with consistent styling and validation support.