smart_chip_field 1.0.0
smart_chip_field: ^1.0.0 copied to clipboard
A Gmail-style chip input widget for Flutter. Create chips from text input with proper backspace handling, validation, and customization.
Smart Chip Field #
A production-ready Flutter package that provides a Gmail-style chip input field. Perfect for email recipients, tags, and multi-select inputs with proper backspace handling.
โจ Features #
- Gmail-Style Backspace Behavior: First press highlights, second press deletes
- Smart Chip Creation: Auto-converts text to chips on Space, Enter, Comma, or Semicolon
- Custom Validation: Built-in email validator with extensible validation system
- Full Customization: Custom chip builders, separators, and styling
- Keyboard Support: Proper handling of physical keyboard events
- No WidgetSpan Issues: Uses a dual-layer architecture that avoids Flutter's text selection limitations
๐ฏ The Problem This Solves #
Existing chip input packages (like chip_inputs_textfield) struggle with backspace behavior because they use WidgetSpan, which Flutter's text selection system treats as a single character. This causes chips to convert back to text instead of being deleted.
Smart Chip Field solves this by using a dual-layer architecture where chips are real widgets alongside the text field, not embedded within it.
๐ฆ Installation #
Add this to your pubspec.yaml:
dependencies:
smart_chip_field: ^1.0.0
Then run:
flutter pub get
๐ Quick Start #
import 'package:smart_chip_field/smart_chip_field.dart';
SmartChipField(
hintText: 'Add recipients',
validator: ChipValidators.email,
separators: const [',', ' ', ';'],
onChanged: (chips) {
print('Current chips: $chips');
},
)
๐ Usage Examples #
Basic Email Input #
SmartChipField(
hintText: 'To: Add recipients',
validator: ChipValidators.email,
onChanged: (emails) {
setState(() {
_recipients = emails;
});
},
)
Custom Validator #
SmartChipField(
hintText: 'Add tags',
validator: (value) {
if (value.length < 3) return 'Tag must be at least 3 characters';
if (value.contains(' ')) return 'Tags cannot contain spaces';
return null; // Valid
},
)
Custom Chip Design #
SmartChipField(
chipBuilder: (text, onDelete) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
decoration: BoxDecoration(
color: Colors.purple.shade100,
borderRadius: BorderRadius.circular(20),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.tag, size: 16),
const SizedBox(width: 4),
Text(text),
const SizedBox(width: 4),
GestureDetector(
onTap: onDelete,
child: Icon(Icons.close, size: 16),
),
],
),
);
},
)
Pre-filled Chips #
SmartChipField(
initialChips: const [
'john@example.com',
'jane@example.com',
],
validator: ChipValidators.email,
)
๐จ Customization Options #
| Parameter | Type | Description |
|---|---|---|
initialChips |
List<String> |
Pre-populated chips |
validator |
String? Function(String)? |
Validation function (return null if valid) |
onChanged |
void Function(List<String>)? |
Called when chips list changes |
separators |
List<String> |
Characters that trigger chip creation (default: [',', ' ']) |
hintText |
String |
Placeholder text when empty |
chipBuilder |
Widget Function(String, VoidCallback)? |
Custom chip widget builder |
๐งช Built-in Validators #
Email Validator #
SmartChipField(
validator: ChipValidators.email,
)
No Spaces Validator #
SmartChipField(
validator: ChipValidators.noSpaces,
)
Combine Multiple Validators #
String? multiValidator(String value) {
final emailError = ChipValidators.email(value);
if (emailError != null) return emailError;
if (value.contains('test')) {
return 'Test emails not allowed';
}
return null;
}
โจ๏ธ Keyboard Behavior #
- Space / Enter / Comma: Creates a chip from current text
- Backspace (first press): Highlights the last chip
- Backspace (second press): Deletes the highlighted chip
- Click chip: Deletes the chip immediately
- Type while chip highlighted: Unhighlights and continues typing
๐๏ธ Architecture #
Unlike traditional approaches that embed chips in text using WidgetSpan, Smart Chip Field uses:
- Chip Layer: Real widgets in a
Wraplayout - Input Layer: Standard
TextFieldfor text entry - Event Interceptor:
Focus.onKeyEventto handle backspace before TextField processes it
This architecture completely avoids Flutter's text selection limitations with WidgetSpan.
๐ Common Issues #
Issue: Chips not creating on space #
Solution: Make sure separators includes ' ' (space character)
Issue: Validation not working #
Solution: Your validator must return null for valid input, and a String error message for invalid input
Issue: Custom chip builder not showing #
Solution: Ensure your chipBuilder returns a complete widget and calls the onDelete callback
๐ License #
MIT License - see LICENSE file for details
๐ค Contributing #
Contributions are welcome! Please open an issue or submit a pull request.
๐ง Support #
If you find this package helpful, please give it a โญ on GitHub and a ๐ on pub.dev!
For bugs or feature requests, please open an issue.