Skip to content

LayrzComboBoxInput

Kenny Mochizuki Escalona edited this page Aug 13, 2026 · 2 revisions

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.

Metadata

Property Value
Mirror ThemedTextInput with enableCombobox: true
Phase M3 Inputs
Domain Inputs
SDK Primitive RawAutocomplete (SDK: autocomplete.dart) + EditableText with custom TextSelectionControls

Conformance Status

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 and Interaction

  • 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)

Deltas from the Input Contract

Combobox-Specific Parameters

// 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,
}

Input Chrome

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;
}

Reference: Current layrz_theme API

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

Dependencies and Blockers

  • 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

Implementation Notes from layrz_theme

  • Overlay focus behavior: The RawAutocomplete overlay 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 position is below but there's no room, it moves above.
  • 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).

Open Questions

  1. 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))?
  2. 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?
  3. Option rendering: Are options:

    • Plain text strings?
    • Can they include icons, colors, or custom widgets?
    • Is there a callback to format option display?
  4. Value type flexibility: Currently, options and value are both String. Should there be a generic LayrzComboBoxInput<T> variant where:

    • Options are of type T
    • A toString() or custom formatter converts T to display string?
  5. Free-form entry: Should the field allow any text the user types, or only text from the options list?

  6. Dropdown open/close control: Can the caller programmatically open/close the dropdown, or is it automatic?

  7. Keyboard navigation in dropdown: Are arrow keys, Enter, and Escape supported to navigate and select options?

  8. Accessibility: Should the dropdown be labeled for screen readers? Should the combobox role be applied?

  9. Material-free TextSelectionControls: Same CRITICAL BLOCKER as for LayrzTextInput. What is the implementation plan?

  10. 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

Clone this wiki locally