-
Notifications
You must be signed in to change notification settings - Fork 0
LayrzSelectInput
Single-value selection field with searchable dropdown list surface.
Specification Status: Derived from
layrz_theme.ThemedSelectInput. 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 | ThemedSelectInput<T> |
| Phase | M3 Inputs |
| Domain | Inputs |
| SDK Primitive | Composes LayrzTextInput (read-only) + RawDialog for dropdown surface |
LayrzSelectInput conforms to the Input Contract. Like all picker-style inputs, it composes LayrzTextInput internally in read-only mode and opens a selection surface on tap. The entire contract applies: labels, prefix/suffix, help affordance, focus management, padding, and validation error display.
-
Value type: Generic
T— any comparable type - Selection surface: Searchable dropdown dialog with a single-selection list
- Summary display: The field displays the label of the selected item; unselected state shows placeholder or empty
-
Item support type:
LayrzSelectItem<T>(derived from layrz_theme'sThemedSelectItem<T>)
LayrzSelectInput introduces a support type, LayrzSelectItem<T>, to represent each selectable item:
// Design sketch — illustrative only
class LayrzSelectItem<T> {
/// Human-readable label displayed in the dropdown list.
final String label;
/// The value returned when this item is selected.
final T? value;
/// Optional icon displayed in the list and/or prefix.
final IconData? icon;
/// Optional custom widget displayed in the list (overrides icon and label).
final Widget? content;
/// Optional custom leading widget (e.g., avatar, thumbnail).
final Widget? leading;
/// Callback invoked when this item is tapped in the list.
final VoidCallback? onTap;
/// Attributes to include in search filtering (e.g., category, code).
final Set<String> searchableAttributes;
const LayrzSelectItem({
required this.label,
required this.value,
this.icon,
this.content,
this.leading,
this.onTap,
this.searchableAttributes = const {},
});
}// Design sketch — illustrative only
class LayrzSelectInput<T> extends StatefulWidget {
/// List of items available for selection.
final List<LayrzSelectItem<T>> items;
/// Callback invoked when user selects an item.
/// Receives the selected item or null if unselected.
final void Function(LayrzSelectItem<T>?)? onChanged;
/// Currently selected value (matched against LayrzSelectItem.value).
final T? value;
/// Whether to enable search filtering in the dropdown.
final bool enableSearch;
/// Whether to automatically close the dropdown after selection.
final bool autoclose;
/// Whether the user can deselect the current item (uncheck it).
final bool canUnselect;
/// Custom filter function for search.
/// If null, performs case-insensitive label search.
final bool Function(String searchText, LayrzSelectItem<T>)? filter;
/// Text displayed when the filtered list is empty.
final String? emptyListText;
/// Constraints for the dropdown dialog size.
final BoxConstraints dialogConstraints;
/// Height of each list item (affects scrollable area).
final double itemExtent;
const LayrzSelectInput({
required this.items,
this.onChanged,
this.value,
this.enableSearch = true,
this.autoclose = true,
this.canUnselect = false,
this.filter,
this.emptyListText,
this.dialogConstraints = const BoxConstraints(maxWidth: 500, maxHeight: 500),
this.itemExtent = 50,
// ... shared contract parameters (label, placeholder, prefix, suffix, etc.)
});
}All of the following are inherited from LayrzTextInput:
- labelText and label (mutually exclusive)
- placeholder
- prefixIcon, prefixWidget, onPrefixTap (mutually exclusive icon and widget)
- suffixIcon, suffixWidget, onSuffixTap (mutually exclusive icon and widget)
- helpTitleText, helpContentText (two-part help tooltip)
- readOnly (always true for select input)
- onTap (opens the dropdown; can be overridden by caller if needed)
- focusNode, controller (focus and value management)
- padding (defaults to spacing tokens)
- disabled and error display
ThemedSelectInput<T> (source: lib/src/inputs/src/general/select_input.dart):
| Parameter | Type | Notes |
|---|---|---|
labelText |
String? |
Label text (or use label Widget instead) |
label |
Widget? |
Label widget (mutually exclusive with labelText) |
items |
List<ThemedSelectItem<T>> |
List of selectable items |
value |
T? |
Currently selected value |
onChanged |
void Function(ThemedSelectItem<T>?)? |
Callback when item selected |
prefixIcon |
IconData? |
Icon in prefix slot |
prefixText |
String? |
Text in prefix slot |
onPrefixTap |
VoidCallback? |
Prefix tap handler |
enableSearch |
bool |
Enable search in dropdown (default: true) |
autoclose |
bool |
Close after selection (default: true) |
canUnselect |
bool |
Allow deselection (default: false) |
disabled |
bool |
Disable the field (default: false) |
errors |
List<String> |
Error messages (default: []) |
hideDetails |
bool |
Hide error/helper text (default: false) |
hideTitle |
bool |
Hide title in dropdown dialog (default: false) |
isRequired |
bool |
Mark field as required (default: false) |
padding |
EdgeInsets? |
Field padding |
filter |
bool Function(String, ThemedSelectItem<T>)? |
Custom search filter |
dialogConstraints |
BoxConstraints |
Dropdown dialog size |
itemExtent |
double |
Height of each list item (default: 50) |
overrideHeightDialog |
double? |
Override computed dialog height |
customChild |
Widget? |
Replace entire input with custom widget |
returnNullOnClose |
bool |
Return null if dialog closed without selection (default: false) |
autoSelectFirst |
bool |
Auto-select first item on first render (default: false) |
translations |
Map<String, String> |
i18n strings (cancel, save, search, empty messages) |
overridesLayrzTranslations |
bool |
Use custom translations over defaults (default: false) |
ThemedSelectItem<T>:
-
label(String): Item display label -
value(T?): Item value -
icon(IconData?): Icon to display -
leading(Widget?): Custom leading widget -
content(Widget?): Custom content (overrides label/icon/leading) -
onTap(VoidCallback?): Item tap callback -
searchableAttributes(Set): Additional searchable text -
isRemoved(bool): Marks item as removed (forcanUnselectflow)
- LayrzTextInput — must ship first; LayrzSelectInput composes it.
-
LayrzTooltip — required for help affordances if using
helpTitleText/helpContentText. - Material-free TextSelectionControls — if LayrzTextInput requires copy/paste in read-only mode, this blocker applies.
-
Naming: Is
LayrzSelectItem<T>the correct name, or should it follow a different pattern (e.g.,SelectOption<T>,MenuItem<T>)? -
Value update semantics: When
valuechanges externally, does the field automatically find and display the matchingLayrzSelectItem, or is the caller responsible for keeping the value in sync with the items list? -
Dialog positioning: Should the dropdown be smart-positioned (above/below based on available space), or always below the field?
-
Custom item rendering: Does
LayrzSelectItem.contenttake precedence overicon,leading, andlabel, or are there specific rendering priorities? -
Search filtering: If
filteris not supplied, does it search all attributes (label + searchableAttributes), or label only? -
Unselect UI: When
canUnselectis true, how is the unselect action presented — a separate button, toggle behavior on the selected item, or both? -
Empty state text: Is there a default empty-list message, or must the caller provide one?
-
Keyboard navigation: Are arrow keys, Enter, and Escape supported in the dropdown list for desktop?
Last updated: 2026-08-13
Related documents: Input Contract, 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