Radio

A radio button component for single-select options within a group

A radio button component for selecting a single option from a group.

When to use this

  • Single selection: Allow users to choose one option from multiple choices
  • Form inputs: Collect single-choice preferences in forms
  • Settings: Enable users to select one configuration option
  • Surveys: Gather responses with mutually exclusive options

Basic implementation

Basic implementation
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';

class RadioExample extends StatefulWidget {
  const RadioExample({super.key});

  @override
  State<RadioExample> createState() => _RadioExampleState();
}

class _RadioExampleState extends State<RadioExample> {
  String? _selectedValue;

  @override
  Widget build(BuildContext context) {
    return RemixRadioGroup<String>(
      groupValue: _selectedValue,
      onChanged: (value) {
        setState(() {
          _selectedValue = value;
        });
      },
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        spacing: 16,
        mainAxisSize: MainAxisSize.min,
        children: [
          Row(
            spacing: 8,
            mainAxisSize: MainAxisSize.min,
            children: [
              RemixRadio<String>(value: 'option1', style: style),
              const Text('Option 1'),
            ],
          ),
          Row(
            spacing: 8,
            mainAxisSize: MainAxisSize.min,
            children: [
              RemixRadio<String>(value: 'option2', style: style),
              const Text('Option 2'),
            ],
          ),
        ],
      ),
    );
  }

  RemixRadioStyle get style {
    return RemixRadioStyle()
        .borderRadiusAll(const Radius.circular(30))
        .size(22, 22)
        .border(
          BoxBorderMix.all(
            BorderSideMix()
                .color(Colors.blueGrey.shade100)
                .width(2.4)
                .strokeAlign(BorderSide.strokeAlignInside),
          ),
        )
        .onHovered(
          RemixRadioStyle().shadow(
            BoxShadowMix()
                .color(Colors.blueGrey.shade50.withValues(alpha: 0.7))
                .blurRadius(0)
                .spreadRadius(9),
          ),
        )
        .onPressed(
          RemixRadioStyle().border(
            BoxBorderMix.all(
              BorderSideMix()
                  .color(Colors.blueGrey.shade100)
                  .width(6)
                  .strokeAlign(BorderSide.strokeAlignInside),
            ),
          ),
        )
        .onSelected(
          RemixRadioStyle().border(
            BoxBorderMix.all(
              BorderSideMix()
                  .color(Colors.blueAccent.shade700)
                  .width(6)
                  .strokeAlign(BorderSide.strokeAlignInside),
            ),
          ),
        );
  }
}

Fortal styles

Remix includes Fortal-themed style helpers for this component:

Fortal variants
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';

class FortalRadioExample extends StatefulWidget {
  const FortalRadioExample({super.key});

  @override
  State<FortalRadioExample> createState() => _FortalRadioExampleState();
}

class _FortalRadioExampleState extends State<FortalRadioExample> {
  String? _selected;

  @override
  Widget build(BuildContext context) {
    return RemixRadioGroup<String>(
      groupValue: _selected,
      onChanged: (value) => setState(() => _selected = value),
      child: Column(
        children: [
          RemixRadio(value: 'soft', style: FortalRadioStyle.soft()),
          RemixRadio(value: 'solid', style: FortalRadioStyle.solid()),
        ],
      ),
    );
  }
}

See the FortalRadioStyle source code for all available options.

Constructor

Constructor
// Radio Group
const RemixRadioGroup({
  Key? key,
  required T? groupValue,
  required ValueChanged<T?>? onChanged,
  required Widget child,
})

// Radio Button
const RemixRadio({
  Key? key,
  required T value,
  bool enabled = true,
  MouseCursor mouseCursor = SystemMouseCursors.click,
  bool enableFeedback = true,
  FocusNode? focusNode,
  bool autofocus = false,
  String? semanticLabel,
  RemixRadioStyle style = const RemixRadioStyle.create(),
  RemixRadioSpec? styleSpec,
})

Properties

Widget Properties

styleRemixRadioStyle

Optional.

styleSpecRemixRadioSpec?

Optional.

keyKey?

Optional. Controls how one widget replaces another widget in the tree.

valueT

Required. The value represented by this radio button.

autofocusbool

Optional. Whether the radio button should automatically request focus when it is created.

enabledbool

Optional. Whether this radio button is enabled.

toggleablebool

Optional. Whether the radio button is toggleable (can be unselected).

focusNodeFocusNode?

Optional. The focus node for the radio button.

mouseCursorMouseCursor?

Optional. The mouse cursor to use when hovering over the radio button.

enableFeedbackbool

Optional. Whether to provide feedback when the radio button is pressed.

Style Methods

indicator(BoxStyler value)

Sets indicator styling (selected fill).

alignment(Alignment value)

Sets container alignment.

padding(EdgeInsetsGeometryMix value)

Convenience for applying padding around the control.

margin(EdgeInsetsGeometryMix value)

Convenience for applying margin around the control.

color(Color value)

Sets background color on the container.

size(double width, double height)

Sets container size using explicit constraints.

borderRadius(BorderRadiusGeometryMix radius)

Sets border radius on the outer container.

animate(AnimationConfig animation)

Sets animation configuration.

wrap(WidgetModifierConfig value)

constraints(BoxConstraintsMix value)

decoration(DecorationMix value)

foregroundDecoration(DecorationMix value)

transform(Matrix4 value, AlignmentGeometry alignment = Alignment.center)