Skip to content
HyperUI for Flutter requires the Style package — this site itself ships no pub package.

Radio Groups

Ported from HyperUI’s Radio Groups — see Attribution.

Includes a dark: variant — toggle the site theme (top right) to preview it.

class RadioGroups1Example extends StatefulWidget {
const RadioGroups1Example({super.key});
@override
State<RadioGroups1Example> createState() => _RadioGroups1ExampleState();
}
class _RadioGroups1ExampleState extends State<RadioGroups1Example> {
var _selected = 0;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-lg p-6',
child: Style(
'space-y-3',
children: [
const Style('sr-only', child: Text('Delivery')),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 0),
child: Style(
'flex items-center justify-between gap-4 rounded border border-gray-300 bg-white p-3 text-sm font-medium shadow-sm transition-colors hover:bg-gray-50 has-checked:border-blue-600 has-checked:ring-1 has-checked:ring-blue-600 dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800',
cursor: SystemMouseCursors.click,
children: [
const Style('text-gray-700 dark:text-gray-200', child: Text('Standard')),
const Style('text-gray-900 dark:text-white', child: Text('Free')),
Style('sr-only', checked: _selected == 0, child: const SizedBox.shrink()),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 1),
child: Style(
'flex items-center justify-between gap-4 rounded border border-gray-300 bg-white p-3 text-sm font-medium shadow-sm transition-colors hover:bg-gray-50 has-checked:border-blue-600 has-checked:ring-1 has-checked:ring-blue-600 dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800',
cursor: SystemMouseCursors.click,
children: [
const Style('text-gray-700 dark:text-gray-200', child: Text('Next Day')),
const Style('text-gray-900 dark:text-white', child: Text('£9.99')),
Style('sr-only', checked: _selected == 1, child: const SizedBox.shrink()),
],
),
),
],
),
);
}
}

Includes a dark: variant — toggle the site theme (top right) to preview it.

class RadioGroups2Example extends StatefulWidget {
const RadioGroups2Example({super.key});
@override
State<RadioGroups2Example> createState() => _RadioGroups2ExampleState();
}
class _RadioGroups2ExampleState extends State<RadioGroups2Example> {
var _selected = 0;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-lg p-6',
child: Style(
'space-y-3',
children: [
const Style('sr-only', child: Text('Delivery')),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 0),
child: Style(
'flex items-center justify-between gap-4 rounded border border-gray-300 bg-white p-3 text-sm font-medium shadow-sm transition-colors hover:bg-gray-50 has-checked:border-blue-600 has-checked:ring-1 has-checked:ring-blue-600 dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800',
cursor: SystemMouseCursors.click,
children: [
Style.empty(
children: [
const Style('text-gray-700 dark:text-gray-200', child: Text('Standard')),
const Style('text-gray-900 dark:text-white', child: Text('Free')),
],
),
Style(
'size-5 border-gray-300 dark:border-gray-600 dark:bg-gray-900 dark:ring-offset-gray-900 dark:checked:bg-blue-600',
formControl: true,
formControlRadio: true,
checked: _selected == 0,
),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 1),
child: Style(
'flex items-center justify-between gap-4 rounded border border-gray-300 bg-white p-3 text-sm font-medium shadow-sm transition-colors hover:bg-gray-50 has-checked:border-blue-600 has-checked:ring-1 has-checked:ring-blue-600 dark:border-gray-600 dark:bg-gray-900 dark:hover:bg-gray-800',
cursor: SystemMouseCursors.click,
children: [
Style.empty(
children: [
const Style('text-gray-700 dark:text-gray-200', child: Text('Next Day')),
const Style('text-gray-900 dark:text-white', child: Text('£9.99')),
],
),
Style(
'size-5 border-gray-300 dark:border-gray-600 dark:bg-gray-900 dark:ring-offset-gray-900 dark:checked:bg-blue-600',
formControl: true,
formControlRadio: true,
checked: _selected == 1,
),
],
),
),
],
),
);
}
}
class RadioGroups3Example extends StatefulWidget {
const RadioGroups3Example({super.key});
@override
State<RadioGroups3Example> createState() => _RadioGroups3ExampleState();
}
class _RadioGroups3ExampleState extends State<RadioGroups3Example> {
var _selected = 0;
@override
Widget build(BuildContext context) {
return Style(
'mx-auto max-w-lg p-6',
child: Style(
'flex flex-wrap gap-3',
children: [
const Style('sr-only', child: Text('Color')),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 0),
child: Style(
'block size-8 rounded-full bg-black shadow-sm has-checked:ring-2 has-checked:ring-black has-checked:ring-offset-2',
cursor: SystemMouseCursors.click,
children: [
Style('sr-only', checked: _selected == 0, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('Black')),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 1),
child: Style(
'block size-8 rounded-full bg-red-500 shadow-sm has-checked:ring-2 has-checked:ring-red-500 has-checked:ring-offset-2',
cursor: SystemMouseCursors.click,
children: [
Style('sr-only', checked: _selected == 1, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('Red')),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 2),
child: Style(
'block size-8 rounded-full bg-blue-500 shadow-sm has-checked:ring-2 has-checked:ring-blue-500 has-checked:ring-offset-2',
cursor: SystemMouseCursors.click,
children: [
Style('sr-only', checked: _selected == 2, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('Blue')),
],
),
),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => setState(() => _selected = 3),
child: Style(
'block size-8 rounded-full bg-amber-500 shadow-sm has-checked:ring-2 has-checked:ring-amber-500 has-checked:ring-offset-2',
cursor: SystemMouseCursors.click,
children: [
Style('sr-only', checked: _selected == 3, child: const SizedBox.shrink()),
const Style('sr-only', child: Text('Gold')),
],
),
),
],
),
);
}
}