-
Notifications
You must be signed in to change notification settings - Fork 0
LayrzTextInput
Single-line text entry field, forming the architectural base for the entire input family.
CONFIRMED by the team. This component is in active scope for Phase M3 and is the essential foundation for all other Layrz*Input components.
| Field | Value |
|---|---|
| Mirrors |
ThemedTextInput from layrz_theme |
| Phase | M3 (Core Inputs) |
| Domain | Inputs |
| Composes | Layers of: EditableText (SDK), Material-free TextSelectionControls (to be provided), LayrzTooltip for help affordances |
| Arch Pattern | Base of composition: all other inputs are built on top of LayrzTextInput |
LayrzTextInput conforms to the shared input contract. This document records only what is specific to this component—parameters, behavior, and architectural requirements that go beyond the contract. For the baseline API (labelText, placeholder, prefix/suffix, help affordances, onChanged, onSubmit, onTap, readOnly, focusNode, controller, padding), refer to the contract.
-
Value type:
String(mutable viaTextEditingController) - Interaction: Direct editing via keyboard input
-
Single-line only: No multiline textarea support in this component. Multiline is deferred to a separate
LayrzTextAreaInputcomponent.
LayrzTextInput adds the following over the base contract:
-
keyboardType(TextInputType) — controls the soft keyboard presented (text, email, phone, number, URL, etc.). Default:TextInputType.text. -
textInputAction(TextInputAction?) — controls the submit/action button on the keyboard (next, done, go, search, etc.). -
inputFormatters(List<TextInputFormatter>) — applied during input to enforce character or format restrictions. -
maxLength(int?) — maximum number of characters allowed. When set, character count may be displayed. -
autofocus(bool) — whether the field requests focus when the widget is first built. Default:false. -
textCapitalization(TextCapitalization) — automatic capitalization rules for input. Default:TextCapitalization.none. -
autocorrect(bool) — whether autocorrection is enabled. Default:true. -
enableSuggestions(bool) — whether text suggestions are shown. Default:true.
The contract specifies icon vs. widget exclusivity. LayrzTextInput clarifies:
-
prefixText(String?) — static prefix text (e.g., "$" for currency, "+" for phone). Distinct from icon or widget. -
suffixText(String?) — static suffix text (e.g., unit labels like "kg", "°C"). - These are independent of icon/widget slots; a field can have a text prefix AND an icon suffix simultaneously.
The contract leaves validator/error handling as an open question. LayrzTextInput's stance:
-
validator(bool Function(String)?) — optional validation function returningtrueif valid,falseotherwise. Invoked when needed (e.g., on form submission). -
errors(List<String>) — list of error messages to display. Rendered by a companionLayrzFieldErrorcomponent below the input (or integrated directly; see blockers). -
hideDetails(bool) — whether to suppress error display. Default:false.
The contract questions whether a disabled state exists distinct from readOnly.
-
disabled(bool) — disables the field: keyboard input is blocked, visual feedback is grayed out or reduced in opacity,onTapis not triggered. Distinct fromreadOnly, which allows focus/selection but not editing. - Default:
false.
-
autofillHints(List<String>) — platform autofill hints (e.g.,AutofillHints.email). Used by password managers and browser autofill.
For porting purposes, the current layrz_theme implementation exposes (non-exhaustive list of key parameters from source):
// Design sketch — shows parameter names found in layrz_theme source
class ThemedTextInput extends StatefulWidget {
final TextInputType keyboardType;
final String? labelText;
final Widget? label; // NOT supported in LayrzTextInput (labelText only)
final String? placeholder;
final String? prefixText;
final IconData? prefixIcon;
final Widget? prefixWidget;
final VoidCallback? onPrefixTap;
final bool prefixIconDisabled;
final bool suffixIconDisabled;
final IconData? suffixIcon;
final String? suffixText;
final VoidCallback? onSuffixTap;
final bool obscureText; // Handled by LayrzPasswordInput, not exposed here
final TextEditingController? controller;
final void Function(String)? onChanged;
final VoidCallback? onTap;
final String? value;
final bool disabled;
final List<String> errors;
final bool hideDetails;
final EdgeInsets? padding;
final bool dense; // NOT ported; layrz_ui uses design tokens only
final bool isRequired; // Markup only; not validated
final FocusNode? focusNode;
final bool Function(String)? validator;
final VoidCallback? onSubmitted;
final TextInputAction? textInputAction;
final bool readonly; // Mapped to readOnly in LayrzTextInput
final List<TextInputFormatter> inputFormatters;
final List<String> autofillHints;
final double? borderRadius; // Controlled by theme, not parameterized
final int maxLines; // For LayrzTextInput, always 1; multiline deferred
final bool autocorrect;
final bool enableSuggestions;
final bool autofocus;
final Widget? suffixWidget;
final List<String> choices; // Combobox support — DEFERRED to LayrzSelectInput
final bool enableCombobox; // Combobox support — DEFERRED
// ... combobox-related params omitted
}Key changes in LayrzTextInput relative to ThemedTextInput:
-
No
labelWidget: labelText only. Rationale: composable inputs need consistent chrome; label widgets break consistency. If needed, render a custom label outside LayrzTextInput. -
No multiline:
maxLinesis always 1. Multiline textarea is a separate component. -
No combobox: Combobox/autocomplete is deferred to
LayrzSelectInput(M3 or later). ThemedTextInput conflates text input and autocomplete; LayrzTextInput is pure text input. -
No
denseparameter: Spacing is controlled entirely by design tokens from LayrzThemeData. No per-field density tuning. -
No
isRequiredmarkup: Required state is visual only (e.g., red asterisk on label). Validation is delegated tovalidatorcallback. -
No
obscureTextparameter: Obscuring (password hide/show toggle) is the job ofLayrzPasswordInput, not LayrzTextInput.
The SDK's EditableText widget requires a concrete TextSelectionControls implementation to handle:
- Text selection handles (mobile draggable endpoints)
- Selection toolbar (cut/copy/paste buttons)
- Desktop toolbar positioning and button layout
Current state: Material provides MaterialTextSelectionControls and Cupertino provides CupertinoTextSelectionControls. Neither can be imported in layrz_ui.
Solution required: Implement a custom, Material-free LayrzTextSelectionControls class.
Available SDK building blocks:
-
RawMagnifier— a magnifying glass widget that shows enlarged selection area during dragging (useful for mobile). -
SystemContextMenu— native system context menu (cut/copy/paste) for platforms that support it (e.g., Android 11+).
Status: BLOCKING. LayrzTextInput cannot proceed to implementation until this is available.
The help affordance uses the tooltip component to render helpTitleText and helpContentText. LayrzTooltip must be available in M2.
Status: Blocking, but M2 precedes M3 in the roadmap.
Text styling (font family, size, weight, color in normal/focused/disabled states) comes from LayrzThemeData. The theme must be in place before styling can be implemented.
Status: M1 work, completed.
CRITICAL: The visual design of LayrzTextInput diverges from ThemedTextInput per internal design review meetings and is not captured in any linked artefact. This gap is a blocker for the entire input family, since every other input composes LayrzTextInput and inherits its chrome.
Required before implementation: A design reference (Figma file, annotated mockup, or design spec) must define:
- Label positioning, typography, and spacing
- Placeholder text styling (color, font, opacity rules for light/dark themes)
- Prefix/suffix icon sizing and spacing
- Focus state appearance (border, shadow, background change)
- Hover state appearance (if any, for desktop)
- Error state appearance (e.g., red border, error icon, error text color)
- Disabled state appearance (opacity, color desaturation, cursor handling)
- Help affordance icon (location, size, visibility rules)
- Padding and overall field dimensions
- Light and dark theme variants
Without this, implementation will guess at design decisions, leading to rework.
The following decisions are not yet made and must be resolved before implementation.
- Is error display integrated into LayrzTextInput itself, or does it delegate to a companion
LayrzFieldErrorcomponent? - If delegated, does LayrzFieldError sit below LayrzTextInput, or does the caller wrap both?
- Is there a color-coded error indicator (e.g., red border when errors exist)?
- Does the help icon (showing helpTitleText and helpContentText) appear always, only when help text is supplied, or only on focus?
- Does it occupy the suffix slot or sit beside a caller-supplied suffix? If both are present, what is the precedence?
- Is the help affordance a separate clickable/hoverable element, or is it integrated with the suffix?
- Are there other
EditableTextconstructor parameters worth exposing (e.g.,minLines,strutStyle,showCursor,cursorColor,cursorWidth,cursorRadius)? - Should the widget expose
styleandtextAlignparameters, or are these locked to theme-derived values?
- Is
disabledvisually distinct fromreadOnlyin all states (focus, hover, text selection)? - Does
disabledprevent focus entirely, or does it allow focus but block input? - Are both states required, or can one subsume the other?
- The current contract suggests
validator: bool Function(String)?, returning true/false. Is this the right contract, or should it return an optional error message string instead (more flexible)?
- M1 (Foundation): Design reference and LayrzThemeData must be finalized.
-
M2 (Core primitives): Implement Material-free
TextSelectionControlsand ship LayrzTooltip. - M3 (Inputs): Implement LayrzTextInput, resolve all open questions, and ship.
- M3 continuation: Implement LayrzNumberInput, LayrzPasswordInput, LayrzCheckboxInput, LayrzRadioInput on top of LayrzTextInput.
- M4 (Pickers): Implement picker inputs (LayrzDateInput, LayrzColorInput, LayrzEmojiInput, etc.) as read-only LayrzTextInput with selection dialogs.
Last updated: 2026-08-13
Related documents: Input Contract, Design Tokens, Flutter 347 Audit
Made with ❤️ by Golden M, Inc.
- LayrzTextInput
- LayrzSelectableAction
- LayrzSelectionToolbar
- LayrzTextSelectionControls
- LayrzSelectionMagnifier
- LayrzSelectionHandlePainter
- LayrzTextAreaInput
- LayrzComboBoxInput
- LayrzNumberInput
- LayrzPasswordInput
- LayrzCheckboxInput
- LayrzRadioInput
- LayrzSelectInput
- LayrzMultiSelectInput
- LayrzSearchInput
- LayrzDualListInput
- LayrzDurationInput
- LayrzSlider
- LayrzStepper