Skip to content

Commit

Permalink
[M3] Add error state support for side property of CheckBox (#118386)
Browse files Browse the repository at this point in the history
* Add error state support for side property

* lint fixes

* lint fixes
  • Loading branch information
esouthren authored Jan 12, 2023
1 parent 0d91c03 commit f1a1f27
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
4 changes: 3 additions & 1 deletion packages/flutter/lib/src/material/checkbox.dart
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@ class Checkbox extends StatefulWidget {
/// * [MaterialState.hovered].
/// * [MaterialState.focused].
/// * [MaterialState.disabled].
/// * [MaterialState.error].
///
/// If this property is not a [MaterialStateBorderSide] and it is
/// non-null, then it is only rendered when the checkbox's value is
Expand Down Expand Up @@ -396,7 +397,8 @@ class _CheckboxState extends State<Checkbox> with TickerProviderStateMixin, Togg

BorderSide? _resolveSide(BorderSide? side) {
if (side is MaterialStateBorderSide) {
return MaterialStateProperty.resolveAs<BorderSide?>(side, states);
final Set<MaterialState> sideStates = widget.isError ? (states..add(MaterialState.error)) : states;
return MaterialStateProperty.resolveAs<BorderSide?>(side, sideStates);
}
if (!states.contains(MaterialState.selected)) {
return side;
Expand Down
79 changes: 79 additions & 0 deletions packages/flutter/test/material/checkbox_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,85 @@ void main() {
await gestureLongPress.up();
await tester.pump();
});

testWidgets('Checkbox MaterialStateBorderSide applies in error states - M3', (WidgetTester tester) async {
final FocusNode focusNode = FocusNode(debugLabel: 'Checkbox');
final ThemeData themeData = ThemeData(useMaterial3: true);
const Color borderColor = Color(0xffffeb3b);
tester.binding.focusManager.highlightStrategy = FocusHighlightStrategy.alwaysTraditional;
bool? value = false;
Widget buildApp({bool autoFocus = true}) {
return MaterialApp(
theme: themeData,
home: Material(
child: Center(
child: StatefulBuilder(builder: (BuildContext context, StateSetter setState) {
return Checkbox(
isError: true,
side: MaterialStateBorderSide.resolveWith((Set<MaterialState> states) {
if (states.contains(MaterialState.error)) {
return const BorderSide(color: borderColor, width: 4);
}
return const BorderSide(color: Colors.red, width: 2);
}),
value: value,
onChanged: (bool? newValue) {
setState(() {
value = newValue;
});
},
autofocus: autoFocus,
focusNode: focusNode,
);
}),
),
),
);
}

void expectBorder() {
expect(
tester.renderObject<RenderBox>(find.byType(Checkbox)),
paints
..drrect(
color: borderColor,
outer: RRect.fromLTRBR(15, 15, 33, 33, const Radius.circular(1)),
inner: RRect.fromLTRBR(19, 19, 29, 29, Radius.zero),
),
);
}

await tester.pumpWidget(buildApp());
await tester.pumpAndSettle();
expectBorder();

// Focused
await tester.pumpWidget(buildApp());
await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isTrue);
expectBorder();

// Default color
await tester.pumpWidget(Container());
await tester.pumpWidget(buildApp(autoFocus: false));
await tester.pumpAndSettle();
expect(focusNode.hasPrimaryFocus, isFalse);
expectBorder();

// Start hovering
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(find.byType(Checkbox)));
await tester.pumpAndSettle();
expectBorder();

// Start pressing
final TestGesture gestureLongPress = await tester.startGesture(tester.getCenter(find.byType(Checkbox)));
await tester.pump();
expectBorder();
await gestureLongPress.up();
await tester.pump();
});
}

class _SelectedGrabMouseCursor extends MaterialStateMouseCursor {
Expand Down

0 comments on commit f1a1f27

Please sign in to comment.