Skip to content

LayrzRadioInput

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

LayrzRadioInput

Radio button group input with generic type support and responsive grid layout.


Specification Status

DERIVED from layrz_theme. This specification is extracted from the current ThemedRadioInput<T> API and awaits team confirmation. Details may change during the M3 inputs review.


Metadata

Field Value
Mirrors ThemedRadioInput<T> from layrz_theme
Phase M3 (Core Inputs)
Domain Inputs
Composes UNCLEAR — possibly a bare radio group, not LayrzTextInput (see Composition Architecture section below)
SDK Primitive RawRadio (raw_radio.dart:44) — design-agnostic radio control, used by both Material and Cupertino

Conformance

LayrzRadioInput does NOT compose LayrzTextInput, as a radio group is not a text field. However, it follows the same spirit as the input contract in terms of:

  • Shared label and error display patterns
  • Responsive layout using the grid system
  • Theme-aware styling

The contract does not apply directly. Refer to Input-Specific API below for the actual interface.


Value Type and Interaction

  • Value type: Generic T (caller-specified, often String or an enum)
  • Selection surface: Inline radio button group (no dialog or popup)
  • Layout: Responsive grid — buttons arranged in columns per breakpoint (1 column on XS, 2 on SM, 3 on MD, etc.)

Composition Architecture — NOT LayrzTextInput

LayrzRadioInput is a bare radio group, not a decorated text field. It does not compose LayrzTextInput because:

  1. Radio groups are not text fields; they have no text editing capability.
  2. The interactive surface is the button grid, not a single field chrome.
  3. The label and errors are rendered at the group level, not per-radio.

However, the component maintains the input contract's spirit:

  • labelText for group label
  • errors and hideDetails for error display
  • padding for consistent spacing
  • disabled for disabling the whole group

Value Type and Item Rendering

LayrzRadioInput is generic: the value and items can be of any type T.

// Design sketch — generic type T
class LayrzRadioInput<T> extends StatefulWidget {
  /// The currently selected value, or null if nothing is selected.
  final T? value;

  /// The list of selectable items, each with a value and label.
  final List<LayrzSelectItem<T>> items;

  /// Callback invoked when the user selects a different value.
  final void Function(T?)? onChanged;

  // ...
}

Each item in the items list has a structure like:

class LayrzSelectItem<T> {
  /// The value associated with this item.
  final T value;

  /// The human-readable label displayed next to the radio button.
  final String label;
}

Deltas from the Input Contract

LayrzRadioInput adds the following over the base patterns:

Items and Values

  • value (T?) — the currently selected value. Corresponds to one of the items' values, or null if nothing is selected.
  • items (List<LayrzSelectItem<T>>, required) — the list of selectable options. Each item has a value and label.

Responsive Grid Layout

  • xsSize (Sizes) — number of columns on extra-small screens (0–599 px). Default: Sizes.col12 (full width, 1 column).
  • smSize (Sizes?) — number of columns on small screens (600–999 px). Default: Sizes.col6 (2 columns).
  • mdSize (Sizes?) — number of columns on medium screens (1000–1399 px). Default: Sizes.col4 (3 columns).
  • lgSize (Sizes?) — number of columns on large screens (1400–1999 px). Default: Sizes.col3 (4 columns).
  • xlSize (Sizes?) — number of columns on extra-large screens (2000+ px). Default: Sizes.col2 (6 columns).

These values correspond to a 12-column responsive grid. Sizes.col12 = 1 item per row, Sizes.col6 = 2 items per row, Sizes.col4 = 3 per row, Sizes.col3 = 4 per row, Sizes.col2 = 6 per row. This allows the radio group to reflow its layout at different screen sizes.

State and Callbacks

  • onChanged (void Function(T?)?) — invoked when the user selects a radio button. Receives the new value (or null if deselection is allowed).
  • disabled (bool) — when true, all radio buttons are not interactive.

Layout and Labels

  • labelText (String?) — label text for the radio group. Rendered above the buttons.
  • label (Widget?) — label widget. NOT supported in layrz_ui (labelText only).
  • padding (EdgeInsets) — padding around the entire group. Default: EdgeInsets.all(10).
  • hideDetails (bool) — whether to suppress error display. Default: false.
  • errors (List<String>) — list of error messages displayed below the group.

Reference: ThemedRadioInput API

For porting purposes, the current layrz_theme implementation exposes (extracted from source):

// Design sketch — parameter names from layrz_theme source
class ThemedRadioInput<T> extends StatefulWidget {
  final String? labelText;
  final Widget? label;              // NOT supported
  final void Function(T?)? onChanged;
  final T? value;
  final List<ThemedSelectItem<T>> items; // Required
  final bool disabled;              // Default: false
  final List<String> errors;        // Default: []
  final bool hideDetails;           // Default: false
  final EdgeInsets padding;         // Default: EdgeInsets.all(10)
  final Sizes xsSize;               // Default: .col12
  final Sizes? smSize;              // Default: .col6
  final Sizes? mdSize;              // Default: .col4
  final Sizes? lgSize;              // Default: .col3
  final Sizes? xlSize;              // Default: .col2
}

Rendering (from source):

  • The component wraps items in a ResponsiveRow container.
  • Each item becomes a ResponsiveCol with the breakpoint-specific size.
  • Inside each column is a Row with a Radio<T> widget and a GestureDetector-wrapped label.
  • Clicking the label toggles the selection.

SDK Primitives for Material-Free Radios

The Flutter SDK provides RawRadio<T> (raw_radio.dart:44), which is:

  • Design-agnostic: Used by both Material and Cupertino without Material/Cupertino imports in the widget's build method.
  • Generically typed: Supports any comparable type T.
  • Constructor:
    RawRadio<T>({
      required T value,
      required T? groupValue,
      required ValueChanged<T?> onChanged,
      bool toggleable = false,
      // ... other Material-specific parameters like fillColor, splashRadius, etc.
    })

Note: RawRadio is design-agnostic for selection logic, but some constructor parameters (e.g., fillColor, splashRadius) are Material-oriented. Custom styling via BuildContext.theme (layrz_ui) must override these for a consistent design.


Dependencies and Blockers

Dependency: RawRadio (SDK)

RawRadio<T> is available in Flutter's SDK without Material/Cupertino imports. No additional dependency or blocker.

Dependency: LayrzSelectItem Type

LayrzRadioInput requires a way to pair values with labels. In layrz_theme, this is ThemedSelectItem<T>. In layrz_ui, this may be renamed to LayrzSelectItem<T> or a similar data class.

Status: Must align with the broader LayrzSelectInput implementation.

Dependency: Responsive Grid System

The responsive layout uses breakpoint sizes from layrz_ui's grid system (xsSize, smSize, mdSize, etc.). This system must be stable in M1.

Status: Available in M1.


Open Questions

1. CRITICAL: Composition Architecture

  • Does LayrzRadioInput compose LayrzTextInput in any form? (Answer: Almost certainly no, since it's not a text field.)
  • Is LayrzRadioInput considered part of the "input family" that conforms to the shared input contract, or is it a separate category?

2. Custom Item Rendering

  • Can the caller provide a custom widget to render each radio item (not just a string label)?
  • If yes, what is the callback signature (e.g., Widget Function(LayrzSelectItem<T>))?

3. Single vs. Multiple Selection

  • Does LayrzRadioInput support multiselect (i.e., multiple values simultaneously), or only single selection?
  • If multiselect is needed, is that a separate LRadioGroupInput or a variant?

4. Toggleability

  • Can the user click a selected radio button again to deselect it (toggle to null), or does it require a separate action?
  • Should toggleable parameter be exposed to control this behavior?

5. Radio Button Styling

  • What is the visual appearance of unselected vs. selected radio buttons?
  • Should custom colors (e.g., fillColor, strokeColor) be exposed as parameters?
  • Should animation (e.g., smooth transition when selecting) be built-in?

6. Label Interaction

  • Is the label text clickable (clicking toggles the selection)?
  • Should there be a separate touch target area around both the radio and label?

7. Keyboard Navigation

  • Should the radio group support arrow keys (← → ↑ ↓) to navigate between options?
  • Should Tab navigate through the group or skip it?

8. Accessibility

  • Are radio buttons announced correctly with screen readers (VoiceOver, TalkBack)?
  • Should each option have a semantic label distinct from its text label (for i18n)?

Last updated: 2026-08-13
Related documents: Input Contract, LayrzTextInput, ./l_checkbox_input.md, Design Tokens

Clone this wiki locally