Headless checkbox component. Handles toggle behavior, keyboard activation, and accessibility. Use builder pattern for custom styling.
- Form selections: Multiple choice options in forms
- Settings toggles: Enable/disable features or preferences
- List selections: Select multiple items from a list
- Agreement confirmations: Terms of service, privacy policies
Information
See complete examples in our GitHub repository.
dart
import 'package:flutter/material.dart';
import 'package:naked_ui/naked_ui.dart';
class CheckboxExample extends StatefulWidget {
const CheckboxExample({super.key});
@override
State<CheckboxExample> createState() => _CheckboxExampleState();
}
class _CheckboxExampleState extends State<CheckboxExample> {
bool _isChecked = false;
@override
Widget build(BuildContext context) {
return NakedCheckbox(
value: _isChecked,
onChanged: (next) => setState(() => _isChecked = next ?? false),
builder: (context, state, _) {
final bool isChecked = state.isChecked == true;
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 20,
height: 20,
decoration: BoxDecoration(
color: isChecked ? Colors.blue : Colors.transparent,
border: Border.all(color: Colors.blue, width: 2),
borderRadius: BorderRadius.circular(4),
),
child: isChecked
? const Icon(Icons.check, size: 14, color: Colors.white)
: null,
),
const SizedBox(width: 8),
const Text('Label'),
],
);
},
);
}
}Information
For tristate checkboxes (supporting null/indeterminate state), set tristate: true and use bool? for the value. The checkbox will cycle through false → true → null → false when tapped.
NakedCheckboxState delivers everything the builder needs:
isChecked→bool?(null when tristate and currently indeterminate)tristate→ whether tristate mode is enabledisIntermediate→ convenience flag for the null casewidgetStates→ hover/focus/pressed/disabled information
NakedCheckboxState.of(context)→ read the nearest scope (throws if missing)NakedCheckboxState.maybeOf(context)→ nullable variantNakedCheckboxState.controllerOf(context)→ access the underlyingWidgetStatesControllerNakedCheckboxState.maybeControllerOf(context)→ nullable controller lookup
dart
const NakedCheckbox({
Key? key,
this.child,
this.value = false,
this.tristate = false,
this.onChanged,
this.enabled = true,
this.mouseCursor,
this.enableFeedback = true,
this.focusNode,
this.autofocus = false,
this.onFocusChange,
this.onHoverChange,
this.onPressChange,
this.builder,
this.semanticLabel,
this.excludeSemantics = false,
})value→ current checked value (bool?whentristate)tristate→ enable false → true → null cyclingonChanged→ receive the next value; omit to render a disabled checkboxbuilder→ValueWidgetBuilder<NakedCheckboxState>?for dynamic visualschild→ static child when you do not need the builder- interaction callbacks:
onFocusChange,onHoverChange,onPressChange semanticLabel→ accessible name announced by screen readersexcludeSemantics→ hide the checkbox and its descendants from the semantic tree
- Ensure the control is labelled either via surrounding text or
semanticLabel - Provide pressed/hover/focus affordances for keyboard and pointer users
- When using
tristate, explain the meaning of the intermediate state in adjacent text - Minimum recommended touch target is 44×44 logical pixels