# WRadio Controlled radio button. Composes `WAnchor` (interaction state) + `WDiv` (outer ring shell) + `WDiv` (inner filled indicator). Drives the `selected:` state prefix when `value == groupValue`, mirroring how `WCheckbox` drives `checked:`. Mutually-exclusive group behavior is the caller's responsibility: pass the same `groupValue` to every `WRadio` in a group and update it through `onChanged`. ## Table of Contents - [Basic Usage](#basic-usage) - [Props](#props) - [Constructor](#constructor) - [Styling Examples](#styling-examples) - [Related Documentation](#related-documentation) ## Basic Usage ```dart WRadio( value: 'light', groupValue: _theme, onChanged: (val) => setState(() => _theme = val), className: ''' w-5 h-5 rounded-full border border-gray-300 dark:border-gray-600 flex items-center justify-center selected:border-blue-500 dark:selected:border-blue-400 hover:border-blue-400 dark:hover:border-blue-300 ''', indicatorClassName: 'w-2.5 h-2.5 rounded-full bg-blue-500 dark:bg-blue-400', ) ``` ## Props | Prop | Type | Default | Description | |:-----|:-----|:--------|:------------| | `value` | `T` | **Required** | The value this radio represents. | | `groupValue` | `T?` | **Required** | The currently selected value for the group. When `value == groupValue`, `selected:` state activates. | | `onChanged` | `ValueChanged?` | `null` | Called with `value` when this radio is tapped and not already selected. Omit or pass `null` for a non-interactive radio. | | `className` | `String?` | `null` | Utility classes for the outer ring shell. Defaults to `'w-5 h-5 rounded-full border border-gray-300 flex items-center justify-center selected:border-primary-500'` when `null`. | | `indicatorClassName` | `String?` | `null` | Utility classes for the inner filled dot (visible only when selected). Defaults to `'w-2.5 h-2.5 rounded-full bg-primary selected:opacity-100'` when `null`. | | `disabled` | `bool` | `false` | Blocks tap and activates the `disabled:` prefix. | | `states` | `Set?` | `null` | Extra custom states merged with built-in `selected` and `disabled`. | | `semanticLabel` | `String?` | `null` | Accessible label for the Semantics node. Required on icon-only radios. | ## Constructor ```dart WRadio({ Key? key, required T value, required T? groupValue, ValueChanged? onChanged, String? className, String? indicatorClassName, bool disabled = false, Set? states, String? semanticLabel, }) ``` ## Styling Examples ### Vertical Radio Group Each radio in the group shares the same `groupValue` and `onChanged`. The `selected:` prefix styles the active choice: ```dart WRadio( value: 'pro', groupValue: _plan, onChanged: (val) => setState(() => _plan = val), className: ''' w-5 h-5 rounded-full border-2 border-gray-300 dark:border-gray-600 flex items-center justify-center selected:border-indigo-500 dark:selected:border-indigo-400 hover:border-indigo-400 dark:hover:border-indigo-300 disabled:opacity-50 ''', indicatorClassName: ''' w-2.5 h-2.5 rounded-full bg-indigo-500 dark:bg-indigo-400 ''', ) ``` ### Horizontal Row Arrange radios in a `flex-row` container for inline selection: ```dart WDiv( className: 'flex flex-row gap-6', children: [ for (final option in ['light', 'dark', 'system']) WDiv( className: 'flex flex-row items-center gap-2', children: [ WRadio( value: option, groupValue: _theme, onChanged: (val) => setState(() => _theme = val), className: 'w-5 h-5 rounded-full border border-gray-300 dark:border-gray-600 flex items-center justify-center selected:border-blue-500 dark:selected:border-blue-400', indicatorClassName: 'w-2.5 h-2.5 rounded-full bg-blue-500 dark:bg-blue-400', ), WText(option, className: 'text-sm text-gray-700 dark:text-gray-300'), ], ), ], ) ``` ### Default Fallback Styling When `className` or `indicatorClassName` is omitted, `WRadio` falls back to its built-in defaults, which route through the theme `primary` token (blue by default; override `primary` in `WindThemeData` to rebrand). Override the classNames only when the design calls for a different tone: ```dart // Uses built-in primary defaults (blue unless the theme's primary is overridden) WRadio( value: 'option', groupValue: _value, onChanged: (val) => setState(() => _value = val), ) ``` ## Related Documentation - [WCheckbox](./w-checkbox.md): boolean input that mirrors the state-prefix pattern. - [WAnchor](./w-anchor.md): provides hover and focus state propagation used by `WRadio` internally. - [WDiv](./w-div.md): renders the ring shell and indicator surfaces.