Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/material_ui/lib/src/button_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,10 @@ class ButtonThemeData with Diagnosticable {
/// If [MaterialButton.textColor] is a [WidgetStateProperty<Color>], it will be
/// used as the `disabledTextColor`. It will be resolved in the [WidgetState.disabled] state.
Color getDisabledTextColor(MaterialButton button) {
return button.textColor ?? button.disabledTextColor ?? colorScheme!.onSurface.withOpacity(0.38);
if (button.textColor is WidgetStateProperty<Color>) {
return button.textColor!;
}
return button.disabledTextColor ?? button.textColor ?? colorScheme!.onSurface.withOpacity(0.38);
}
Comment on lines 398 to 403

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The implementation of getDisabledTextColor does not resolve WidgetStateProperty<Color> as documented in the doc comment. If button.textColor is a WidgetStateProperty<Color> (such as WidgetStateColor), it should be resolved in the WidgetState.disabled state when button.disabledTextColor is null.

  Color getDisabledTextColor(MaterialButton button) {
    if (button.disabledTextColor != null) {
      return button.disabledTextColor!;
    }
    if (button.textColor is WidgetStateProperty<Color>) {
      return (button.textColor as WidgetStateProperty<Color>).resolve(<WidgetState>{WidgetState.disabled});
    }
    return button.textColor ?? colorScheme!.onSurface.withOpacity(0.38);
  }


/// The [button]'s background color when [MaterialButton.onPressed] is null
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
changelog: |
- Fixes MaterialButton using textColor instead of disabledTextColor when disabled.
version: patch
72 changes: 72 additions & 0 deletions packages/material_ui/test/material_button_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,78 @@ void main() {
expect(material.color, const Color(0xff00ff00));
});

testWidgets('Disabled MaterialButton prefers disabledTextColor over textColor', (
WidgetTester tester,
) async {
// Regression test for https://github.com/flutter/flutter/issues/127449.

final Finder rawButtonMaterial = find.descendant(
of: find.byType(MaterialButton),
matching: find.byType(Material),
);

await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: MaterialButton(
onPressed: null,
textColor: Colors.blue,
disabledTextColor: Colors.red,
child: Text('button'),
),
),
);

final Material material = tester.widget<Material>(rawButtonMaterial);
expect(material.textStyle!.color, Colors.red);
});

testWidgets(
'Disabled MaterialButton resolves stateful textColor when disabledTextColor is null',
(WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MaterialButton(
onPressed: null,
textColor: WidgetStateColor.resolveWith((Set<WidgetState> states) {
return states.contains(WidgetState.disabled) ? Colors.grey : Colors.blue;
}),
child: const Text('button'),
),
),
);

final Material material = tester.widget<Material>(
find.descendant(of: find.byType(MaterialButton), matching: find.byType(Material)),
);
expect(material.textStyle!.color, Colors.grey);
},
);

testWidgets('Disabled MaterialButton prefers stateful textColor over disabledTextColor', (
WidgetTester tester,
) async {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: MaterialButton(
onPressed: null,
textColor: WidgetStateColor.resolveWith((Set<WidgetState> states) {
return states.contains(WidgetState.disabled) ? Colors.grey : Colors.blue;
}),
disabledTextColor: Colors.red,
child: const Text('button'),
),
),
);

final Material material = tester.widget<Material>(
find.descendant(of: find.byType(MaterialButton), matching: find.byType(Material)),
);
expect(material.textStyle!.color, Colors.grey);
});

testWidgets(
'Default MaterialButton meets a11y contrast guidelines',
(WidgetTester tester) async {
Expand Down
Loading