Skip to content

Commit 58ac0dc

Browse files
authored
Fix label text color is wrong for a focused and hovered TextField (#146572)
Before, hovering a focused TextField would incorrect change the label color. Now it does not, which is correct per the spec.
1 parent 7db26b0 commit 58ac0dc

File tree

3 files changed

+373
-65
lines changed

3 files changed

+373
-65
lines changed

dev/tools/gen_defaults/lib/input_decorator_template.dart

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,16 @@ class _${blockName}DefaultsM3 extends InputDecorationTheme {
2121
late final ColorScheme _colors = Theme.of(context).colorScheme;
2222
late final TextTheme _textTheme = Theme.of(context).textTheme;
2323
24+
// For InputDecorator, focused state should take precedence over hovered state.
25+
// For instance, the focused state increases border width (2dp) and applies bright
26+
// colors (primary color or error color) while the hovered state has the same border
27+
// than the non-focused state (1dp) and uses a color a little darker than non-focused
28+
// state. On desktop, it is also very common that a text field is focused and hovered
29+
// because users often rely on mouse selection.
30+
// For other widgets, hovered state takes precedence over focused state, because it
31+
// is mainly used to determine the overlay color,
32+
// see https://github.com/flutter/flutter/pull/125905.
33+
2434
@override
2535
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
2636
if (states.contains(MaterialState.disabled)) {
@@ -139,20 +149,20 @@ class _${blockName}DefaultsM3 extends InputDecorationTheme {
139149
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.disabled.label-text')});
140150
}
141151
if (states.contains(MaterialState.error)) {
142-
if (states.contains(MaterialState.hovered)) {
143-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.label-text')});
144-
}
145152
if (states.contains(MaterialState.focused)) {
146153
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.focus.label-text')});
147154
}
155+
if (states.contains(MaterialState.hovered)) {
156+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.label-text')});
157+
}
148158
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.label-text')});
149159
}
150-
if (states.contains(MaterialState.hovered)) {
151-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.label-text')});
152-
}
153160
if (states.contains(MaterialState.focused)) {
154161
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.focus.label-text')});
155162
}
163+
if (states.contains(MaterialState.hovered)) {
164+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.label-text')});
165+
}
156166
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.label-text')});
157167
});
158168
@@ -163,20 +173,20 @@ class _${blockName}DefaultsM3 extends InputDecorationTheme {
163173
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.disabled.label-text')});
164174
}
165175
if (states.contains(MaterialState.error)) {
166-
if (states.contains(MaterialState.hovered)) {
167-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.label-text')});
168-
}
169176
if (states.contains(MaterialState.focused)) {
170177
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.focus.label-text')});
171178
}
179+
if (states.contains(MaterialState.hovered)) {
180+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.label-text')});
181+
}
172182
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.label-text')});
173183
}
174-
if (states.contains(MaterialState.hovered)) {
175-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.label-text')});
176-
}
177184
if (states.contains(MaterialState.focused)) {
178185
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.focus.label-text')});
179186
}
187+
if (states.contains(MaterialState.hovered)) {
188+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.label-text')});
189+
}
180190
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.label-text')});
181191
});
182192
@@ -185,24 +195,24 @@ class _${blockName}DefaultsM3 extends InputDecorationTheme {
185195
final TextStyle textStyle = ${textStyle("md.comp.filled-text-field.supporting-text")} ?? const TextStyle();
186196
if (states.contains(MaterialState.disabled)) {
187197
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.disabled.supporting-text')});
188-
}${componentColor('md.comp.filled-text-field.hover.supporting-text') == componentColor('md.comp.filled-text-field.supporting-text') ? '' : '''
189-
if (states.contains(MaterialState.hovered)) {
190-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.supporting-text')});
191-
}'''}${componentColor('md.comp.filled-text-field.focus.supporting-text') == componentColor('md.comp.filled-text-field.supporting-text') ? '' : '''
198+
}${componentColor('md.comp.filled-text-field.focus.supporting-text') == componentColor('md.comp.filled-text-field.supporting-text') ? '' : '''
192199
if (states.contains(MaterialState.focused)) {
193200
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.focus.supporting-text')});
201+
}'''}${componentColor('md.comp.filled-text-field.hover.supporting-text') == componentColor('md.comp.filled-text-field.supporting-text') ? '' : '''
202+
if (states.contains(MaterialState.hovered)) {
203+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.hover.supporting-text')});
194204
}'''}
195205
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.supporting-text')});
196206
});
197207
198208
@override
199209
TextStyle? get errorStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
200210
final TextStyle textStyle = ${textStyle("md.comp.filled-text-field.supporting-text")} ?? const TextStyle();${componentColor('md.comp.filled-text-field.error.hover.supporting-text') == componentColor('md.comp.filled-text-field.error.supporting-text') ? '' : '''
201-
if (states.contains(MaterialState.hovered)) {
202-
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.supporting-text')});
203-
}'''}${componentColor('md.comp.filled-text-field.error.focus.supporting-text') == componentColor('md.comp.filled-text-field.error.supporting-text') ? '' : '''
204211
if (states.contains(MaterialState.focused)) {
205212
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.focus.supporting-text')});
213+
}'''}${componentColor('md.comp.filled-text-field.error.focus.supporting-text') == componentColor('md.comp.filled-text-field.error.supporting-text') ? '' : '''
214+
if (states.contains(MaterialState.hovered)) {
215+
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.hover.supporting-text')});
206216
}'''}
207217
return textStyle.copyWith(color: ${componentColor('md.comp.filled-text-field.error.supporting-text')});
208218
});

packages/flutter/lib/src/material/input_decorator.dart

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4617,6 +4617,16 @@ class _InputDecoratorDefaultsM3 extends InputDecorationTheme {
46174617
late final ColorScheme _colors = Theme.of(context).colorScheme;
46184618
late final TextTheme _textTheme = Theme.of(context).textTheme;
46194619

4620+
// For InputDecorator, focused state should take precedence over hovered state.
4621+
// For instance, the focused state increases border width (2dp) and applies bright
4622+
// colors (primary color or error color) while the hovered state has the same border
4623+
// than the non-focused state (1dp) and uses a color a little darker than non-focused
4624+
// state. On desktop, it is also very common that a text field is focused and hovered
4625+
// because users often rely on mouse selection.
4626+
// For other widgets, hovered state takes precedence over focused state, because it
4627+
// is mainly used to determine the overlay color,
4628+
// see https://github.com/flutter/flutter/pull/125905.
4629+
46204630
@override
46214631
TextStyle? get hintStyle => MaterialStateTextStyle.resolveWith((Set<MaterialState> states) {
46224632
if (states.contains(MaterialState.disabled)) {
@@ -4705,20 +4715,20 @@ class _InputDecoratorDefaultsM3 extends InputDecorationTheme {
47054715
return textStyle.copyWith(color: _colors.onSurface.withOpacity(0.38));
47064716
}
47074717
if (states.contains(MaterialState.error)) {
4708-
if (states.contains(MaterialState.hovered)) {
4709-
return textStyle.copyWith(color: _colors.onErrorContainer);
4710-
}
47114718
if (states.contains(MaterialState.focused)) {
47124719
return textStyle.copyWith(color: _colors.error);
47134720
}
4721+
if (states.contains(MaterialState.hovered)) {
4722+
return textStyle.copyWith(color: _colors.onErrorContainer);
4723+
}
47144724
return textStyle.copyWith(color: _colors.error);
47154725
}
4716-
if (states.contains(MaterialState.hovered)) {
4717-
return textStyle.copyWith(color: _colors.onSurfaceVariant);
4718-
}
47194726
if (states.contains(MaterialState.focused)) {
47204727
return textStyle.copyWith(color: _colors.primary);
47214728
}
4729+
if (states.contains(MaterialState.hovered)) {
4730+
return textStyle.copyWith(color: _colors.onSurfaceVariant);
4731+
}
47224732
return textStyle.copyWith(color: _colors.onSurfaceVariant);
47234733
});
47244734

@@ -4729,20 +4739,20 @@ class _InputDecoratorDefaultsM3 extends InputDecorationTheme {
47294739
return textStyle.copyWith(color: _colors.onSurface.withOpacity(0.38));
47304740
}
47314741
if (states.contains(MaterialState.error)) {
4732-
if (states.contains(MaterialState.hovered)) {
4733-
return textStyle.copyWith(color: _colors.onErrorContainer);
4734-
}
47354742
if (states.contains(MaterialState.focused)) {
47364743
return textStyle.copyWith(color: _colors.error);
47374744
}
4745+
if (states.contains(MaterialState.hovered)) {
4746+
return textStyle.copyWith(color: _colors.onErrorContainer);
4747+
}
47384748
return textStyle.copyWith(color: _colors.error);
47394749
}
4740-
if (states.contains(MaterialState.hovered)) {
4741-
return textStyle.copyWith(color: _colors.onSurfaceVariant);
4742-
}
47434750
if (states.contains(MaterialState.focused)) {
47444751
return textStyle.copyWith(color: _colors.primary);
47454752
}
4753+
if (states.contains(MaterialState.hovered)) {
4754+
return textStyle.copyWith(color: _colors.onSurfaceVariant);
4755+
}
47464756
return textStyle.copyWith(color: _colors.onSurfaceVariant);
47474757
});
47484758

0 commit comments

Comments
 (0)