Skip to content

LayrzCheckboxInput

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

LayrzCheckboxInput

Boolean toggle input with support for checkbox, switch, and dropdown field styles.


Specification Status

DERIVED from layrz_theme. This specification is extracted from the current ThemedCheckboxInput API and awaits team confirmation. Details may change during the M3 inputs review. CRITICAL OPEN QUESTION: Whether this component composes LayrzTextInput at all (see Composition Architecture section below).


Metadata

Field Value
Mirrors ThemedCheckboxInput from layrz_theme
Phase M3 (Core Inputs)
Domain Inputs
Composes UNCLEAR — may or may not compose LayrzTextInput (see open questions)
SDK Primitive ToggleableStateMixin (toggleable.dart:37) + ToggleablePainter (toggleable.dart:409) for checkbox/switch rendering; hand-rolled toggleable controls

Conformance

LayrzCheckboxInput conditionally conforms to the shared input contract:

  • If style: .asField (dropdown field style): Conforms fully and may compose LayrzTextInput.
  • If style: .asCheckbox or style: .asSwitch (bare checkbox or switch): Does NOT conform to the input contract, as these are not text fields. See Composition Architecture section below.

Only input-specific deltas are documented here.


Value Type and Interaction

  • Value type: bool (three-state toggleable, but often boolean only)
  • Interaction: Click/tap to toggle
  • Three rendering styles (controlled by style parameter):
    1. asCheckbox: Inline checkbox control (✓ / ☐)
    2. asSwitch: Inline toggle switch (ON / OFF)
    3. asField: Dropdown field (renders as "Yes"/"No" selection in a styled text field)

Composition Architecture — CRITICAL OPEN QUESTION

The fundamental question: Does LayrzCheckboxInput compose LayrzTextInput at all?

Current Situation (layrz_theme)

The source shows that ThemedCheckboxInput._buildAsField() composes ThemedSelectInput<bool>, not a text field:

// From layrz_theme source
Widget _buildAsField() {
  return ThemedSelectInput<bool>(
    labelText: widget.labelText,
    label: widget.label,
    // ... configured to display Yes/No options
  );
}

This means:

  • The .asField style DOES compose another input (a select input), so it inherits the input contract via SelectInput.
  • The .asCheckbox and .asSwitch styles are bare toggleables, NOT text fields.

Design Decision Required

For layrz_ui, the team must decide:

Option A: LayrzCheckboxInput composes LayrzTextInput ONLY for .asField style

  • .asField → renders as read-only LayrzTextInput with a dropdown affordance opening a Yes/No picker.
  • .asCheckbox and .asSwitch → separate bare toggleable components, NOT inputs in the family. May be re-homed to a LToggle* family or remain as part of LayrzCheckboxInput for convenience.
  • Implication: The input contract applies only to .asField; checkbox/switch are not contract members.

Option B: LayrzCheckboxInput does NOT compose LayrzTextInput

  • All three styles (checkbox, switch, field) are independent control renderings, grouped under one component name for convenience.
  • The input contract is NOT inherited; LayrzCheckboxInput has its own minimal contract.
  • Implication: Only the .asField style maintains form-field semantics (label, errors, padding); the others are bare controls.

Option C: Split into Multiple Components

  • LayrzCheckboxInput — bare checkbox using SDK primitives, NOT a form input.
  • LSwitchInput — bare switch using SDK primitives, NOT a form input.
  • LayrzSelectInput<bool> — field-style with Yes/No dropdown (existing as generic select).
  • Implication: Cleaner architecture (one concern per component), but breaks the layrz_theme API parity.

Deltas from the Input Contract

Assuming LayrzCheckboxInput is retained as a single component with three styles:

Styling

  • style (ThemedCheckboxInputStyle, enum) — determines the visual rendering:
    • .asCheckbox — Flutter-native checkbox (Material-free using SDK primitives).
    • .asSwitch — Material-free toggle switch.
    • .asField — yes/no dropdown field (read-only text field with picker).
    • .asCheckbox2 — alternative checkbox design (use TBD, possibly for future design refresh). Default: .asCheckbox.

State and Callbacks

  • value (bool) — the current boolean state. Default: false.
  • onChanged (void Function(bool)?) — invoked when the user toggles the state.
  • disabled (bool) — when true, the control is not interactive.

Layout and Labels

  • labelText (String?) — label text. Applicable to all styles. For .asCheckbox and .asSwitch, may render beside or below the control.
  • label (Widget?) — label widget. NOT supported in layrz_ui (labelText only).
  • padding (EdgeInsets) — padding around the control. Default: EdgeInsets.all(10).
  • hideDetails (bool) — whether to suppress error display. Applicable mainly to .asField style.
  • errors (List<String>) — list of error messages.

Reference: ThemedCheckboxInput API

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

// Design sketch — parameter names from layrz_theme source
enum ThemedCheckboxInputStyle {
  asField,              // Dropdown field
  asSwitch,             // Toggle switch
  asFlutterCheckbox,    // Standard checkbox
  asCheckbox2,          // Alternative checkbox
}

class ThemedCheckboxInput extends StatefulWidget {
  final String? labelText;
  final Widget? label;              // NOT supported
  final void Function(bool)? onChanged;
  final bool value;                 // Default: false
  final bool disabled;              // Default: false
  final List<String> errors;        // Default: []
  final bool hideDetails;           // Default: false
  final EdgeInsets padding;         // Default: EdgeInsets.all(10)
  final ThemedCheckboxInputStyle style; // Default: .asFlutterCheckbox
}

Rendering implementations (from source):

  • .asField → internally uses ThemedSelectInput<bool> with hardcoded Yes/No options.
  • .asSwitch → uses Flutter's Switch widget (Material widget — will need Material-free replacement).
  • .asFlutterCheckbox → uses Flutter's Checkbox widget (Material widget — will need Material-free replacement).
  • .asCheckbox2 → alternative checkbox design (source shows same logic as .asFlutterCheckbox but flagged asNewDesign: true).

SDK Primitives for Material-Free Toggleables

Since layrz_ui cannot use Material's Checkbox or Switch widgets, the following SDK primitives are available:

For Checkbox and Switch Rendering

ToggleableStateMixin (flutter/src/material/checkbox.dart, line ~37)

  • Provides internal state management for toggleable controls (checked/unchecked/tristate).
  • Abstract mixin; must be mixed into a custom State class.
  • Handles long-press, keyboard interaction (space/enter), and focus visualization.

ToggleablePainter (flutter/src/material/toggleable.dart, line ~409)

  • Abstract painter for rendering toggle controls.
  • Provides utilities like paintRadialReaction() for ripple effects and animations.
  • Subclass to implement custom checkbox or switch rendering via CustomPaint.

RawRadio and toggle derivatives

  • RawRadio (raw_radio.dart:44) is design-agnostic and used by both Material and Cupertino.
  • No equivalent RawCheckbox or RawSwitch exists in the SDK.

Recommendation

Implement custom toggle controls using ToggleableStateMixin + CustomPaint for rendering, or explore whether the internal Checkbox and Switch implementations can be extracted without Material dependencies. Cupertino's toggle switch may also be Material-free and reusable.


Dependencies and Blockers

Blocker: Material-Free Toggle Controls

Both Checkbox and Switch from Flutter's Material design are not importable in layrz_ui. Custom Material-free implementations must be provided.

Status: Blocking implementation until resolved.

Dependency: LayrzTextInput (Conditionally)

If .asField style composes LayrzTextInput or LayrzSelectInput, those inputs must be available first.

Status: Conditional on composition architecture decision (see open questions).


Open Questions

1. CRITICAL: Composition Architecture

  • Does LayrzCheckboxInput compose LayrzTextInput? If so, only for which styles?
  • Should all three styles (checkbox, switch, field) remain in one component, or split into separate components?
  • Refer to the Composition Architecture section for discussion.

2. Checkbox and Switch Visual Design

  • For .asCheckbox, what is the visual appearance (size, color, animation, disabled state)?
  • For .asSwitch, what is the visual appearance (thumb/track colors, animation, disabled state)?
  • Should animations (check animation, switch sliding) be smooth or instant?

3. Label Positioning

  • For .asCheckbox and .asSwitch, is the label rendered to the right of the control, to the left, or above?
  • Is the label clickable (clicking the label toggles the control)?

4. Error Display

  • How are errors rendered for .asCheckbox and .asSwitch styles? Below the control, beside it, or via a tooltip?
  • For .asField, errors are inherited from the select input rendering.

5. Keyboard Interaction

  • Should checkbox/switch support keyboard toggle (Space or Enter to toggle)?
  • Should they support Tab navigation?

6. Three-State Support

  • Does the checkbox support indeterminate/tristate (true, false, null), or only boolean (true, false)?
  • If tristate, how is the null state visually represented and transitioned between states?

Last updated: 2026-08-13
Related documents: Input Contract, LayrzTextInput, ./l_radio_input.md, Flutter 347 Audit

Clone this wiki locally