-
Notifications
You must be signed in to change notification settings - Fork 0
LayrzComboBoxInput
Autocomplete text field with searchable dropdown options.
Specification Status: Derived from combobox mode of
layrz_theme.ThemedTextInput. This documentation reflects the current layrz_theme API and is NOT YET CONFIRMED as the design for layrz_ui. Team review and design sign-off are required before implementation.
| Property | Value |
|---|---|
| Mirror |
ThemedTextInput with enableCombobox: true
|
| Phase | M3 Inputs |
| Domain | Inputs |
| SDK Primitive |
RawAutocomplete (SDK: autocomplete.dart) + EditableText with custom TextSelectionControls
|
Architectural question: LayrzComboBoxInput differs fundamentally from picker-style inputs and even from plain LayrzTextInput. It composes an EDITABLE text field (not read-only like pickers) combined with a dropdown overlay showing filtered options. This is distinct from:
- LayrzTextInput: Static text editing, no autocomplete
- LayrzSelectInput: Read-only field opening a modal with single selection
- LayrzTextAreaInput: Multiline editable text, no autocomplete
Should LayrzComboBoxInput:
- Inherit the Input Contract's standard API (label, prefix, suffix, help, etc.)?
- Or is it a separate implementation pattern?
-
Value type:
String— the user-entered or selected text - Interaction pattern: An editable text field with a dropdown overlay showing options that match the user's input
- Selection options: Options from a provided list, filtered by the user's typed text
-
Confirmation: User can either:
- Click an option to select it (auto-fills the field)
- Continue typing and press Enter to submit the manual entry
- Blur the field to finalize (behavior configurable)
// Design sketch — illustrative only
class LayrzComboBoxInput extends StatefulWidget {
/// The current text content (user-typed or selected).
final String? value;
/// Callback invoked when the text changes.
final void Function(String)? onChanged;
/// Callback invoked when the user submits (selects an option or presses Enter).
final void Function(String)? onSubmit;
/// List of autocomplete options.
/// These strings are matched against the user's input for filtering.
final List<String> options;
/// Maximum number of options to display in the dropdown.
final int maxOptionsToDisplay;
/// Whether to enable autocomplete filtering.
/// If false, all options are always displayed.
final bool enableAutocomplete;
/// Text displayed when the filtered options list is empty.
final String emptyOptionsText;
/// Position of the dropdown: above or below the field.
final LComboboxPosition position;
/// Placeholder text shown when the field is empty.
final String? placeholder;
/// Keyboard type (text, URL, email, etc.).
final TextInputType keyboardType;
/// Text input action (e.g., TextInputAction.done, .next).
final TextInputAction textInputAction;
const LayrzComboBoxInput({
required this.options,
this.value,
this.onChanged,
this.onSubmit,
this.maxOptionsToDisplay = 5,
this.enableAutocomplete = true,
this.emptyOptionsText = 'No options',
this.position = .below,
this.placeholder,
this.keyboardType = .text,
this.textInputAction = .done,
// ... shared contract parameters (label, prefix, suffix, help, etc.)
});
}
enum LComboboxPosition {
/// Dropdown appears below the text field.
below,
/// Dropdown appears above the text field.
above,
}Inherits some Input Contract chrome, but with differences:
// Design sketch — shared with LayrzTextInput (editable variant):
class LayrzComboBoxInput {
/// Label displayed above the field.
final String? labelText;
/// Custom label widget (mutually exclusive with labelText).
final Widget? label;
/// Placeholder/hint text (shown when empty).
final String? placeholder;
/// Icon in the prefix slot.
final IconData? prefixIcon;
/// Custom widget in the prefix slot (mutually exclusive with prefixIcon).
final Widget? prefixWidget;
/// Callback when prefix is tapped.
final VoidCallback? onPrefixTap;
/// Icon in the suffix slot (often a dropdown arrow).
final IconData? suffixIcon;
/// Custom widget in the suffix slot (mutually exclusive with suffixIcon).
final Widget? suffixWidget;
/// Callback when suffix is tapped.
final VoidCallback? onSuffixTap;
/// Help title for tooltip.
final String? helpTitleText;
/// Help content for tooltip.
final String? helpContentText;
/// Padding inside the field.
final EdgeInsets? padding;
/// Error messages to display below the field.
final List<String> errors;
/// Whether to display errors and help text.
final bool hideDetails;
/// Focus node for managing focus.
final FocusNode? focusNode;
/// Text controller for external value management.
final TextEditingController? controller;
/// Whether the field is disabled.
final bool disabled;
/// Character input formatters.
final List<TextInputFormatter> inputFormatters;
}ThemedTextInput with enableCombobox: true (source: lib/src/inputs/src/general/text_input.dart):
| Parameter | Type | Notes |
|---|---|---|
value |
String? |
Current text content |
onChanged |
void Function(String)? |
Text change callback |
onSubmitted |
VoidCallback? |
Submit callback |
controller |
TextEditingController? |
Text controller |
choices |
List<String> |
Autocomplete option list |
enableCombobox |
bool |
Enable combobox mode (default: false) |
maxChoicesToDisplay |
int |
Max options shown (default: 5) |
emptyChoicesText |
String |
Empty list message (default: "No choices") |
position |
ThemedComboboxPosition |
Dropdown position: above or below (default: below) |
labelText |
String? |
Label text |
label |
Widget? |
Label widget |
placeholder |
String? |
Placeholder text |
prefixIcon |
IconData? |
Icon in prefix slot |
prefixWidget |
Widget? |
Custom prefix widget |
onPrefixTap |
VoidCallback? |
Prefix tap handler |
suffixIcon |
IconData? |
Icon in suffix slot |
suffixWidget |
Widget? |
Custom suffix widget |
onSuffixTap |
VoidCallback? |
Suffix tap handler |
errors |
List<String> |
Error messages |
hideDetails |
bool |
Hide errors/help text |
padding |
EdgeInsets? |
Field padding |
disabled |
bool |
Disable the field |
focusNode |
FocusNode? |
Focus node |
keyboardType |
TextInputType |
Keyboard type (default: text) |
textInputAction |
TextInputAction? |
Enter key behavior |
inputFormatters |
List<TextInputFormatter> |
Input formatters |
autofillHints |
List<String> |
Autofill hints |
autocorrect |
bool |
Spell check (default: true) |
enableSuggestions |
bool |
Suggestions (default: true) |
textStyle |
TextStyle? |
Custom text style |
ThemedComboboxPosition enum:
-
below: Dropdown below the field -
above: Dropdown above the field
- RawAutocomplete (SDK) — the core autocomplete overlay mechanism
-
EditableText + custom TextSelectionControls — CRITICAL BLOCKER. Same as LayrzTextInput and LayrzTextAreaInput. Requires:
- Text selection (tap and drag)
- Copy/paste (long-press or keyboard)
- Cut operations
- Desktop selection toolbar
- Mobile selection handles with magnifier
-
Overlay focus behavior: The
RawAutocompleteoverlay is excluded from ambient focus traversal, so Tab navigation skips it. - Option filtering: Options are filtered case-insensitively by matching the start of each option against the user's typed text.
-
Dropdown positioning: The dropdown is smart-positioned based on available screen space. If
positionisbelowbut there's no room, it movesabove. - Option selection: Clicking an option fills the field with the option text.
- Manual entry: User can type any text, not just options. Pressing Enter or Tab submits the manual entry.
- Blur behavior: When the field loses focus, the dropdown closes (behavior may be configurable).
-
Separate component or factory?: Should LayrzComboBoxInput be:
- A distinct widget class (recommended for clarity)?
- A factory constructor of LayrzTextInput (e.g.,
LayrzTextInput.combobox())? - Or a parameter-driven variant (e.g.,
LayrzTextInput(enableCombobox: true))?
-
Option matching and filtering: Does option matching:
- Match from the start of each option?
- Match anywhere in the option?
- Use a custom filter function?
- Case-sensitive or case-insensitive?
-
Option rendering: Are options:
- Plain text strings?
- Can they include icons, colors, or custom widgets?
- Is there a callback to format option display?
-
Value type flexibility: Currently, options and value are both
String. Should there be a genericLayrzComboBoxInput<T>variant where:- Options are of type
T - A
toString()or custom formatter convertsTto display string?
- Options are of type
-
Free-form entry: Should the field allow any text the user types, or only text from the options list?
-
Dropdown open/close control: Can the caller programmatically open/close the dropdown, or is it automatic?
-
Keyboard navigation in dropdown: Are arrow keys, Enter, and Escape supported to navigate and select options?
-
Accessibility: Should the dropdown be labeled for screen readers? Should the combobox role be applied?
-
Material-free TextSelectionControls: Same CRITICAL BLOCKER as for LayrzTextInput. What is the implementation plan?
-
Distinguishing from LayrzSelectInput: When should a user choose LayrzComboBoxInput (editable, free-form) vs. LayrzSelectInput (read-only, restricted to options)? Should documentation clarify the use cases?
Last updated: 2026-08-13
Related documents: Input Contract, Flutter 347 Audit, Component Catalog, Design Tokens
Made with ❤️ by Golden M, Inc.
- LayrzTextInput
- LayrzSelectableAction
- LayrzSelectionToolbar
- LayrzTextSelectionControls
- LayrzSelectionMagnifier
- LayrzSelectionHandlePainter
- LayrzTextAreaInput
- LayrzComboBoxInput
- LayrzNumberInput
- LayrzPasswordInput
- LayrzCheckboxInput
- LayrzRadioInput
- LayrzSelectInput
- LayrzMultiSelectInput
- LayrzSearchInput
- LayrzDualListInput
- LayrzDurationInput