Skip to content

LayrzTextAreaInput

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

LayrzTextAreaInput

Multiline text entry field for longer prose, notes, and descriptions.

Specification Status: Derived from multiline 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 maxLines > 1
Phase M3 Inputs
Domain Inputs
SDK Primitive EditableText with custom TextSelectionControls

Conformance Status

Architectural question: LayrzTextAreaInput is distinct from picker-style inputs because it needs an EDITABLE text field, not a read-only one. Unlike LayrzSelectInput, LayrzDateInput, etc., it cannot follow the "compose a read-only LayrzTextInput, open a dialog" pattern.

Should LayrzTextAreaInput:

  • Inherit the Input Contract's standard API (label, prefix, suffix, help affordances, focus, etc.)?
  • Or is it a separate implementation that reuses the Input Contract's visual chrome but not the composition pattern?

Value Type and Interaction

  • Value type: String — multiline text content
  • Interaction pattern: A resizable text box with scrolling support
  • Summary display: Shows text directly (not summarized into a single line)
  • Line count: Configurable via minLines, maxLines, and expandable height

Deltas from the Input Contract

Multiline Editing

// Design sketch — illustrative only
class LayrzTextAreaInput extends StatefulWidget {
  /// The current text content.
  final String? value;

  /// Callback invoked when the text changes.
  final void Function(String)? onChanged;

  /// Callback invoked when the user submits (if applicable).
  final void Function(String)? onSubmit;

  /// Minimum number of lines displayed (expands if content exceeds this).
  final int minLines;

  /// Maximum number of lines before scrolling is enabled.
  final int maxLines;

  /// Maximum number of characters allowed (if any).
  final int? maxLength;

  /// Placeholder text shown when empty.
  final String? placeholder;

  /// Keyboard type (multiline text, numbers, punctuation, etc.).
  final TextInputType keyboardType;

  /// Text input action (e.g., TextInputAction.newline for Enter behavior).
  final TextInputAction textInputAction;

  /// Input formatters to apply (e.g., length limits, character filters).
  final List<TextInputFormatter> inputFormatters;

  const LayrzTextAreaInput({
    required this.value,
    this.onChanged,
    this.onSubmit,
    this.minLines = 3,
    this.maxLines = 10,
    this.maxLength,
    this.placeholder,
    this.keyboardType = .multiline,
    this.textInputAction = .newline,
    this.inputFormatters = const [],
    // ... shared contract parameters (label, prefix, suffix, help, errors, etc.)
  });
}

Input Chrome

Inherits the full Input Contract chrome:

// Design sketch — shared with LayrzTextInput:
class LayrzTextAreaInput {
  /// 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.
  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;

  /// Whether the field is read-only (editing not allowed).
  final bool readOnly;

  /// Character count display (optional).
  final bool showCharacterCount;
}

Focus and Lifecycle

Same disposal contract as LayrzTextInput:

  • If focusNode is null, the widget creates one and disposes it when the widget is disposed.
  • If focusNode is provided by the caller, the widget does NOT dispose it.
  • If controller is null, the widget creates one and disposes it.
  • If controller is provided by the caller, the widget does NOT dispose it.

Reference: Current layrz_theme API

ThemedTextInput with maxLines > 1 (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? Submitted callback (Enter on desktop)
controller TextEditingController? Text controller
labelText String? Label text
label Widget? Label widget
placeholder String? Placeholder text
maxLines int Max lines before scrolling (default: 1; >1 for textarea)
minLines Not exposed (Inferred from current layrz_theme; may need to be explicit in layrz_ui)
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
readonly bool Read-only (no editing)
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)
autofocus bool Auto-focus on mount
obscureText bool Mask text (for password-like fields)

Dependencies and Blockers

  • Material-free TextSelectionControls — CRITICAL BLOCKER. The SDK's EditableText requires a concrete TextSelectionControls implementation. Material's version must be replaced with a hand-rolled Material Design Free version that provides:
    • Text selection (tap and drag to select)
    • Copy/paste (long-press or keyboard shortcuts)
    • Cut operations
    • Selection toolbar with context menu (desktop)
    • Mobile selection handles with magnifier
    • Undo/redo if desired

This is the same blocker as for LayrzTextInput and the entire input family.

Implementation Notes from layrz_theme

  • Multiline detection: maxLines > 1 enables multiline mode. When maxLines is 1 (the default), the field is single-line.
  • Line-limited scrolling: If content exceeds maxLines, the field becomes vertically scrollable.
  • Enter key: In multiline mode, Enter inserts a newline (does not submit by default).
  • Character limit: If maxLength is set, the field is limited to that many characters. Some input formatters can enforce this.

Open Questions

  1. Separate component or factory?: Should LayrzTextAreaInput be:

    • A distinct widget class (recommended for clarity)?
    • A factory constructor of LayrzTextInput (e.g., LayrzTextInput.multiline())?
    • Or a parameter-driven variant (e.g., LayrzTextInput(isMultiline: true))?
  2. Minimum line count: Should there be an explicit minLines parameter to control the initial height, or is it inferred from maxLines?

  3. Character count display: Should the field optionally show "123 / 500" character count below the field? Is this built-in or handled via suffix widget?

  4. Resizability: Can the user resize the textarea by dragging a corner handle, or is height fixed by maxLines?

  5. Word wrap and overflow: Is text always wrapped within the field width, or can it overflow horizontally?

  6. Undo/redo support: Should undo/redo be built-in or depend on the caller's controller?

  7. Spell-check and suggestions: On mobile, should there be platform-specific spell-check overlays? Should autocorrect and enableSuggestions be exposed in layrz_ui?

  8. Material-free TextSelectionControls: This is a CRITICAL BLOCKER. What is the implementation plan for copy/paste, selection toolbar, and mobile selection handles?


Last updated: 2026-08-13
Related documents: Input Contract, Flutter 347 Audit, Component Catalog, Design Tokens

Clone this wiki locally