FlutterWidgets
VisorChipSearchInput
A search input that holds selected items as inline chip pills, with a generic type parameter for arbitrary item shapes.
VisorChipSearchInput<T> combines a text query field with inline chip pills
representing the user's current selection. It is the Flutter counterpart of
the React search-input + tag-input combined pattern. The generic T
parameter lets consumers supply any item shape; labelBuilder extracts the
display string for each chip.
Preview
When to Use
- Multi-select search surfaces (filter pickers, recipient pickers, tag entry)
- Any UI where the user builds a query by adding and removing labelled tokens
- Search bars that need to show active filter chips inline with the input
When Not to Use
- Simple single-value search (use a plain
TextFieldorVisorTextInput) - Static chip groups where no typing is involved (use
VisorChip) - Forms that need full validation support (use
VisorTextInput)
Installation
npx visor add chip-search-input --target flutterOr copy components/flutter/visor_chip_search_input/visor_chip_search_input.dart
into your project.
Basic Usage
import 'package:ui/ui.dart';
class TagItem {
TagItem(this.id, this.label);
final String id;
final String label;
}
VisorChipSearchInput<TagItem>(
selectedItems: _selected,
labelBuilder: (item) => item.label,
hintText: 'Add tagsβ¦',
onQueryChanged: _runSearch,
onItemRemoved: (item) => setState(() => _selected.remove(item)),
)API Reference
| Property | Type | Default | Description |
|---|---|---|---|
selectedItems | List<T> | required | Items currently selected, rendered as inline chips |
labelBuilder | String Function(T) | required | Returns the display label for a given item |
hintText | String | required | Placeholder shown when the field is empty |
onQueryChanged | ValueChanged<String> | required | Fires on every query keystroke |
onItemRemoved | ValueChanged<T> | required | Fires when the user removes a chip |
controller | TextEditingController? | null | Optional external text controller |
focusNode | FocusNode? | null | Optional external focus node |
onFocusChanged | ValueChanged<bool>? | null | Fires when focus enters or leaves the field |
onSubmitted | ValueChanged<String>? | null | Fires on keyboard submit |
autofocus | bool | false | Request focus on first build |
enabled | bool | true | When false, renders at reduced opacity and ignores input |
Accessibility
- Backspace on an empty field removes the last chip (Gmail / Slack UX).
- Each chip's remove button is labelled
'Remove <label>'and meets the 48 dp tap target. - Animations honour
MediaQuery.disableAnimationsβ chip add/remove collapses to instant snaps when reduce-motion is requested. - Field uses
EdgeInsetsDirectionalfor RTL layout.
Source
components/flutter/visor_chip_search_input/visor_chip_search_input.dart- Quality contract audit row:
docs/flutter-widget-quality-contract.md(Rec8)