Skip to content

LayrzIconInput

Kenny Mochizuki Escalona edited this page Aug 20, 2026 · 3 revisions

LayrzIconInput

An icon selection field that composes LayrzTextInput and opens a searchable icon grid to pick an icon from the layrz_icons set.

Metadata
Mirrors: ThemedIconPicker (layrz_theme)
Phase: M4 (Pickers)
Domain: Pickers
Primitive: Custom implementation (grid rendering + search)
Status: Derived from layrz_theme. Not yet team-confirmed.


⚠️ IMPORTANT: Specification Status

This page is derived from analysis of ThemedIconPicker in layrz_theme and represents planning assumptions only. The specification has not been reviewed or confirmed by the team. Implementation details, parameter names, and behavior may change during the M4 design phase.

All details below are subject to revision.


Overview

LayrzIconInput renders a read-only LayrzTextInput with a thumbnail preview of the selected icon in the prefix slot. Tapping the field opens a searchable dialog displaying the full layrz_icons set organized by icon family or search results. The user selects an icon, and the field displays the icon's name.

Icon Source

Icons come from the layrz_icons package (version 1.1.0), which is verified clean (no Material/Cupertino coupling). The package exposes 14,572 icon getters across 8 font families:

  1. Material Design Icons
  2. Font Awesome Brands
  3. Font Awesome Solid
  4. Font Awesome Regular
  5. Solar Outline
  6. Solar Bold
  7. Solar Broken
  8. Solar Linear

Note: While the rest of the layrz_ui design system renders icons from flutter_material_design_icons (as MdiIcons.*), LayrzIconInput is intentionally built to browse and select from the layrz_icons Solar set. This is a deliberate design choice; the widget's purpose is to provide access to the full Solar icon catalogue for advanced use cases requiring broader icon variety.

Composition

LayrzIconInput is a thin wrapper over LayrzTextInput configured as read-only. It follows the input family pattern (see Input Contract).


Conformance

LayrzIconInput conforms to the Layrz*Input family contract defined in Input Contract. Inherited parameters:

  • labelText (String) — the only label representation.
  • placeholder — shown inside the field when no icon is selected.
  • prefixIcon / prefixWidget / onPrefixTap — mutually exclusive icon or widget in the leading slot.
  • suffixIcon / suffixWidget / onSuffixTap — mutually exclusive icon or widget in the trailing slot.
  • helpTitleText / helpContentText — help affordance (tooltip).
  • onTap — callback when the field is tapped (opens the icon picker).
  • readOnly — always true for LayrzIconInput.
  • focusNode / controller — standard lifecycle management.
  • padding — customizable per-field; defaults to M1 spacing tokens.

See the input contract for the complete shared API and disposal guarantees.


Value Type and Selection Surface

Value Type

// Design sketch — illustrative only
class LayrzIconInput extends LayrzTextInput {
  /// The currently selected icon.
  ///
  /// Null if no icon is selected.
  /// Type: LayrzIcon (from layrz_icons package).
  final LayrzIcon? value;

  // ...
}

Stores a single LayrzIcon value, which encapsulates both the icon data and metadata (family, name).

Selection Surface

Type: Modal dialog
Layout: Grid of icon previews, organized by family with a search field
Interaction: Tap an icon to select; click Cancel to discard

When the user taps the field:

  1. A dialog opens with icons organized by family (tabs or a scrollable list).
  2. A search field allows filtering icons by name.
  3. The user either browses by family or searches.
  4. Tapping an icon previews it and selects it.
  5. Cancel closes the dialog without changing the selection; OK confirms.
  6. onChanged is invoked with the selected LayrzIcon.

Deltas from Base Contract

LayrzIconInput adds the following to the base LayrzTextInput contract:

// Design sketch — illustrative only
class LayrzIconInput extends LayrzTextInput {
  /// The currently selected icon.
  /// Null if no icon is selected.
  final LayrzIcon? value;

  /// Callback invoked when the user selects an icon.
  final ValueChanged<LayrzIcon>? onChanged;

  /// Allowed icons to display in the picker.
  ///
  /// If empty (default), all 14,572 icons are shown.
  /// Supply a filtered list to constrain the picker to a subset
  /// (e.g., only Solar icons, or only solid icons).
  final List<LayrzIcon> allowedIcons;

  /// Translations for picker UI strings.
  ///
  /// Required keys:
  /// - 'actions.cancel': Cancel button
  /// - 'actions.save': Save/OK button
  /// - 'helpers.search': Search field placeholder
  /// 
  /// If not supplied, default English strings are used.
  /// If [LayrzAppLocalizations] is in the widget tree,
  /// translations are sourced from there automatically.
  final Map<String, String> translations;

  /// Whether to override layrz_theme's default translations.
  ///
  /// Useful if caller-supplied [translations] should take precedence.
  final bool overridesLayrzTranslations;

  // ...
}

Reference: layrz_theme API

ThemedIconPicker exposes these parameters (simplified):

class ThemedIconPicker extends StatefulWidget {
  final String? labelText;
  final Widget? label;
  final void Function(LayrzIcon)? onChanged;
  final LayrzIcon? value;
  final bool disabled;
  final List<String> errors;
  final bool hideDetails;
  final EdgeInsets? padding;
  final bool isRequired;
  final FocusNode? focusNode;
  final Map<String, String> translations;
  final bool overridesLayrzTranslations;
  final List<LayrzIcon> allowedIcons;
  final Widget? customChild;
  // ... Material-specific color/focus/splash parameters
}

Differences for layrz_ui:

  • Remove all Material-specific color/focus/splash parameters.
  • Inherit from base LayrzTextInput contract rather than re-declare shared parameters.
  • dense is not supported (removed from the entire input family; see decision D47); drop isRequired parameter.
  • Remove customChild (M1 foundation does not support arbitrary wrapping).

Grid Virtualization Consideration

Performance concern: layrz_icons exposes 14,572 icon getters. Rendering all of them in a grid simultaneously would be prohibitively slow on mobile and low-end devices.

Recommendation:

  • Virtualize the grid using a ListView.builder or GridView.builder so only visible icons are rendered.
  • Lazy-load icon data from layrz_icons on-demand (avoid loading the entire 14,572-icon set into memory at once).
  • Search optimization: When the user types a search query, filter the icon set before rendering.

This is a critical implementation detail; verify it is addressed during M4 planning.


Icon Display and Naming

Icon Preview in Prefix Slot

The selected icon is displayed in the prefix slot as a visual thumbnail. layrz_theme shows the icon in a ThemedAvatar component.

Icon Name Display

The text field displays the icon's name (e.g., "solarOutlinePalette" or a human-readable equivalent). The exact naming scheme depends on how layrz_icons exposes icon metadata.

Open question: How is the icon name retrieved from a LayrzIcon instance? Is there a .name property, or must it be serialized/deserialized via converters?


Dependencies

  • M1 Theme System (LayrzTheme, LayrzThemeData) — colors and text styling.
  • M2 Tooltip Component (LayrzTooltip) — for help affordance.
  • M3 LayrzTextInput — base field chrome and behavior.
  • layrz_icons 1.1.0 (verified clean) — the icon source; provides 14,572 icons across 8 families.

Implementation Notes

Icon Families and Organization

layrz_icons groups icons into 8 families. The picker should organize the grid by family, allowing users to browse by category (e.g., "All Solar Icons", "Font Awesome Solid", etc.). Verify the exact family names and organization in the layrz_icons source.

Search Implementation

The search field should:

  • Filter icons by name (case-insensitive substring match).
  • Update the grid in real-time as the user types.
  • Support clearing the search to show all icons again.

Icon Size in Grid

What should icons be rendered at in the grid? Recommend: 32×32 or 48×48 logical pixels, with padding around each icon for touch target sizing.


Open Questions

  • Icon accessor form: How are icons accessed from layrz_icons? Is it LayrzIcon.solarOutlineAlbum (static getter), or LayrzIcons.solarOutlineAlbum? Confirm the exact form.

  • Icon metadata: Does LayrzIcon expose name, family, or other metadata? Or must the icon be serialized/matched against the full 14,572-entry mapping to retrieve metadata?

  • Search scope: When filtering by allowedIcons, should search only look within the subset, or across all 14,572 with visual indication that results are filtered?

  • Default selection: If value is null, should the picker open to a specific family (e.g., "Solar Outline"), or show a generic "No selection" state?

  • Grid layout on mobile: On narrow screens (phones), should the icon grid be a single column, or 2-3 columns? Recommend responsive layout tied to screen width.

  • Icon previews during selection: Should hovering/tapping an icon in the grid show a preview in a larger size before confirming the selection?


Design Reference Gap

Critical path item: A design reference (Figma, spec, or annotated screenshot) must be provided before M4 implementation begins, specifying:

  • Icon grid layout (columns, row height, icon size, spacing).
  • Family tabs or selector (how to switch between icon sets).
  • Search field placement and styling.
  • Icon preview size and placement (when selected or hovered).
  • Dialog chrome (padding, buttons, title).
  • Keyboard navigation (Tab to grid, arrow keys to navigate, Enter to select).
  • Screen reader labels for icon grid items.
  • Responsive behavior on phone, tablet, and desktop.
  • Light and dark theme variants.

Last updated: 2026-08-13
Related documents: Input Contract, Dependencies, Design Tokens, Architecture, Roadmap

Clone this wiki locally