Tinyrack

Combobox

Search and select one or several typed options while keeping query and selection state separate.

Search and select one or several typed options with query and selection state kept separate.

Contract

AxisContract
StateThe query and the selected value are separate axes. TRComboboxController owns the value plus the TextEditingController and FocusNode; TRCombobox.controlled hands the value back to you while the controller keeps the query.
FieldThe field is a TRTextField, so label, placeholder, helperText, errorText, uiSize, and width behave exactly as they do there. clearable adds a clear button in the trailing slot once the field holds a query or a selection.
Layer sizelayerSize is independent from the field width. The complete options layer matches its anchor and grows with content up to TRMeasurements.measureXl high by default.
FilteringoptionsBuilder decides the candidates and filterMode narrows them: contains, startsWith, or none. A filter callback overrides filterMode. Use none when a remote or asynchronous optionsBuilder is already authoritative.
MultipleTRMultiCombobox renders committed values as removable chips above the field and clears the query after each pick. layout: TRComboboxLayout.grid lays the popup out in two columns instead of a list.
InteractionArrow keys move the highlight, Enter commits it, and Escape closes the popup. autoHighlight decides whether Enter can commit the first match before any arrow key. Options with enabled: false stay visible, render muted, and are skipped by both Enter and arrow navigation.
FormsTRComboboxFormField and TRMultiComboboxFormField are FormField subclasses, so validator, onSaved, autovalidateMode, and Form.reset work as usual and errorText is supplied by the field state.

Reach for a combobox when the option list is long enough that typing beats scrolling but the committed value must still come from that list. Use TRSelect for a short fixed list, and TRAutocomplete when free text the user typed is itself a valid answer.

Install

Add the package, then import its public library.

flutter pub add tinyrack_ui
import 'package:tinyrack_ui/tinyrack_ui.dart';

Playground

Usage

import 'package:material_ui/material_ui.dart';
import 'package:tinyrack_ui/tinyrack_ui.dart';

TRCombobox<String>(
  label: 'Channel',
  placeholder: 'Choose a channel',
  items: const [
    TRComboboxItem(value: 'stable', label: 'Stable'),
    TRComboboxItem(value: 'beta', label: 'Beta'),
  ],
  onValueChange: selectChannel,
)

Examples

Filter and commit one rack permalink

Typing narrows the popup while the committed value stays separate from the query. Selecting a rack writes its label back into the field.

Sizes permalink

Pass uiSize to align the combobox with neighboring TRTextField, TRSelect, or TRButton heights.

Selected and disabled options permalink

An option with enabled set to false stays in the popup so the reason it is unavailable remains visible. It renders muted and both Enter and arrow navigation skip it.

Filter semantics permalink

Compare contains, startsWith, and no built-in narrowing. Use none when an asynchronous optionsBuilder already returns the matches it wants shown.

Multiple chips and grid popup permalink

TRMultiCombobox renders committed values as removable chips and clears the query after each pick. The grid layout fits short labels into two columns.

Required option and recovery permalink

TRComboboxFormField reports its error through errorText and clears it as soon as a value is committed, so the reader can recover without submitting again.

Controlled state and a custom filter permalink

The controlled constructor hands the value back to the caller while the controller keeps the query. A filter callback replaces filterMode when the built-in rules are not enough.

Popup width and layering permalink

Flutter has no portal or positioner parts. The popup opens on the combobox layer and takes its width from the field, or from the small overlay width token when width is left unset.

Keyboard selection permalink

With autoHighlight off, Enter commits nothing until an arrow key highlights a row. The clear button returns focus to the field so the popup stays open.

Single and multiple fields permalink

The FormField variants keep query text separate from typed selections and participate in validation, save, and reset.

API

TRCombobox properties

PropType / defaultPurpose
itemsList<TRComboboxItem<T>> · const []Supplies the option source. Either items or optionsBuilder must be non-empty.
optionsBuilderTRComboboxOptionsBuilder<T>? · nullReturns candidates for a query, synchronously or as a Future. Its result is still narrowed by filterMode unless that is none.
filterModeTRComboboxFilterMode · containsMatches option labels case-insensitively with contains or startsWith, or skips narrowing with none. Comparison uses toLowerCase, so it is not accent-insensitive the way the React useFilter collator is.
filterTRComboboxFilter<T>? · nullReplaces filterMode with a custom predicate. The query it receives is already trimmed and lower-cased.
autoHighlightbool · trueKeeps the first match armed so Enter commits it immediately. Set it to false to require an arrow key first. It defaults to true here because the underlying RawAutocomplete always keeps a valid highlight index, unlike the React default.
clearable, clearSemanticLabelbool · false, String · 'Clear'Shows a clear button while the field holds a query or a selection. Clearing empties the query, reports null through onValueChange, and returns focus to the field.
controller, defaultValue, valueTRComboboxController<T>?, T?, T?Chooses the state model. defaultValue seeds the uncontrolled constructor, value is required by TRCombobox.controlled, and a controller can be shared with either.
onQueryChange, onValueChangeValueChanged<String>?, ValueChanged<T?>?Report query edits and committed selections separately. onValueChange also fires with null when the clear button is used.
layoutTRComboboxLayout · listDraws the popup as a single-column list or a two-column grid.
enabled, readOnlybool · true, bool · falseDisable interaction, or keep a focusable field whose query cannot be edited. Both hide the clear button.
label, placeholder, helperText, errorTextString? · nullDescribe the field and its validation state through the underlying TRTextField.
uiSize, widthTRUiSize · TRUiSize.md, double? · nullSet the control size and an optional fixed field width. Use layerSize for the popup.
layerSizeTRLayerSize · match anchor / content height ≤ measureXlSizes the complete options layer for single, multiple, and FormField variants.

TRMultiCombobox properties

PropType / defaultPurpose
defaultValue, valueList<T> · const [], List<T>?Hold the committed values. value is required by TRMultiCombobox.controlled and makes the widget fully controlled.
onValueChangeValueChanged<List<T>>? · nullReports the full selection after every pick, chip removal, or clear. Selecting an already selected value removes it.
controllerTRMultiComboboxController<T>? · nullOwns the values and the shared query field. Its clear resets the values only, so clear the textEditingController too when driving it directly.

Items and enums

PropType / defaultPurpose
TRComboboxItem.value, labelT · required, String · requiredCarry the typed value and the text shown in the popup and written back into the field on commit.
TRComboboxItem.enabledbool · trueMarks an option as unselectable. It stays in the popup, renders with the muted text color, and is skipped by keyboard navigation.
TRComboboxItem.leading, trailingWidget? · nullPlace icons on either side of the option label.
TRComboboxLayoutlist, gridSelects the popup arrangement. grid uses two columns of fixed-height rows.
TRComboboxFilterModecontains, startsWith, noneSelects the built-in narrowing rule applied to the option source.

Controllers and form fields

PropType / defaultPurpose
TRComboboxControllerChangeNotifierExposes value, select, and clear alongside the owned textEditingController and focusNode. Dispose it with the widget that created it.
TRMultiComboboxControllerChangeNotifierExposes values, replace, toggle, and clear. values is an unmodifiable view, so replace the list instead of mutating it.
TRComboboxFormFieldFormField<T>Participates in validation and save callbacks with a typed selected value, and feeds errorText back into the field.
TRMultiComboboxFormFieldFormField<List<T>>Does the same for a list of values, so a validator can require at least one selection.