A toggle group presents a compact set of mutually exclusive options. Only one item is in the Tab order; arrow keys move focus without changing selection.
Interactive preview
When to use this
- View switching: Choose list, grid, or board presentation
- Formatting choices: Pick one alignment or text mode
- Compact filters: Select one option from a short, visible set
- Toolbar controls: Preserve focus-only arrow navigation until activation
Basic implementation
class ViewToggle extends StatefulWidget {
const ViewToggle({super.key});
@override
State<ViewToggle> createState() => _ViewToggleState();
}
class _ViewToggleState extends State<ViewToggle> {
String _value = 'list';
@override
Widget build(BuildContext context) {
return FortalToggleGroup<String>(
items: const [
RemixToggleGroupItem(
value: 'list',
label: 'List',
icon: Icons.view_list,
),
RemixToggleGroupItem(
value: 'grid',
label: 'Grid',
icon: Icons.grid_view,
),
RemixToggleGroupItem(
value: 'board',
label: 'Board',
icon: Icons.view_kanban,
),
],
selectedValue: _value,
onChanged: (value) {
if (value != null) setState(() => _value = value);
},
semanticLabel: 'View style',
);
}
}Keyboard behavior
Tabenters on the selected item, or the first enabled item when none is selected- A second
Tableaves the group instead of visiting every item Arrow Left/Arrow Rightmove focus in horizontal groupsArrow Up/Arrow Downmove focus in vertical groupsHome/Endmove focus to the first / last enabled itemSpace/Enteractivate the focused item- Arrow movement wraps when
loopis true and clamps when false - Horizontal arrow direction follows the ambient text direction in RTL layouts
Arrow, Home, and End keys move focus only. Selection changes after explicit activation with Space, Enter, or a pointer.
Value and enabled-state contract
- Item values are non-null, unique keys with stable equality and hash codes
selectedValue: nullmeans no selection; otherwise it must match one item- An empty
itemslist is valid whenselectedValueis null - At most one item may set
autofocus: true onChanged: nulldisables the entire group, just likeenabled: false
Rebuild with a new item list when values or ordering change. Do not mutate the list or a value’s equality behavior while it is rendered.
Visible text supplies an item’s accessible name. Icon-only items must provide a
non-empty semanticLabel; an explicit semantic label replaces the visible
label for accessibility services instead of being announced in addition to it.
Per-item styling
The group’s item style is the default for every option. An item’s style is
merged afterward, so one option can add a local treatment while retaining group
states and sizing.
The group styler controls structural container styling and context variants such
as brightness, breakpoints, and text direction. Put hover, press, focus,
selected, and disabled variants on RemixToggleGroupItemStyler; they resolve
independently for each option. A raw styleSpec is authoritative and bypasses
both the group and per-item fluent stylers.
RemixToggleGroup<String>(
items: [
const RemixToggleGroupItem(value: 'draft', label: 'Draft'),
RemixToggleGroupItem(
value: 'published',
label: 'Published',
style: RemixToggleGroupItemStyler().foregroundColor(Colors.green),
),
],
selectedValue: value,
onChanged: onChanged,
style: RemixToggleGroupStyler().item(
RemixToggleGroupItemStyler()
.paddingX(12)
.paddingY(8)
.onSelected(.color(Colors.green.shade50)),
),
)Constructor
const RemixToggleGroup<T>({
Key? key,
required List<RemixToggleGroupItem<T>> items,
required T? selectedValue,
ValueChanged<T?>? onChanged,
bool enabled = true,
Axis orientation = Axis.horizontal,
bool loop = true,
String? semanticLabel,
bool excludeSemantics = false,
RemixToggleGroupStyler style = const RemixToggleGroupStyler.create(),
RemixToggleGroupSpec? styleSpec,
})const RemixToggleGroupItem<T>({
required T value,
String? label,
IconData? icon,
String? semanticLabel,
bool enabled = true,
FocusNode? focusNode,
bool autofocus = false,
RemixToggleGroupItemStyler style =
const RemixToggleGroupItemStyler.create(),
})Fortal widgets
FortalToggleGroup provides soft and surface variants plus three sizes.
The recipe uses edge-to-edge items, a bordered surface container, selected
accent colors, a visible keyboard focus ring, and disabled state styling.
See the fortalToggleGroupStyler source code for all available options.