Skip to content

Commit 700de09

Browse files
authored
Change button and label text to sentence case for Material 3 (#115187)
* init * upper case only when material 2 * fix test * fix test * fix tests again * Add all tests * analyze" * fix stepper
1 parent 136b46b commit 700de09

File tree

12 files changed

+398
-47
lines changed

12 files changed

+398
-47
lines changed

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

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -318,22 +318,24 @@ class AboutDialog extends StatelessWidget {
318318
final String name = applicationName ?? _defaultApplicationName(context);
319319
final String version = applicationVersion ?? _defaultApplicationVersion(context);
320320
final Widget? icon = applicationIcon ?? _defaultApplicationIcon(context);
321+
final ThemeData themeData = Theme.of(context);
322+
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
321323
return AlertDialog(
322324
content: ListBody(
323325
children: <Widget>[
324326
Row(
325327
crossAxisAlignment: CrossAxisAlignment.start,
326328
children: <Widget>[
327-
if (icon != null) IconTheme(data: Theme.of(context).iconTheme, child: icon),
329+
if (icon != null) IconTheme(data: themeData.iconTheme, child: icon),
328330
Expanded(
329331
child: Padding(
330332
padding: const EdgeInsets.symmetric(horizontal: 24.0),
331333
child: ListBody(
332334
children: <Widget>[
333-
Text(name, style: Theme.of(context).textTheme.headlineSmall),
334-
Text(version, style: Theme.of(context).textTheme.bodyMedium),
335+
Text(name, style: themeData.textTheme.headlineSmall),
336+
Text(version, style: themeData.textTheme.bodyMedium),
335337
const SizedBox(height: _textVerticalSeparation),
336-
Text(applicationLegalese ?? '', style: Theme.of(context).textTheme.bodySmall),
338+
Text(applicationLegalese ?? '', style: themeData.textTheme.bodySmall),
337339
],
338340
),
339341
),
@@ -345,7 +347,11 @@ class AboutDialog extends StatelessWidget {
345347
),
346348
actions: <Widget>[
347349
TextButton(
348-
child: Text(MaterialLocalizations.of(context).viewLicensesButtonLabel),
350+
child: Text(
351+
themeData.useMaterial3
352+
? localizations.viewLicensesButtonLabel
353+
: localizations.viewLicensesButtonLabel.toUpperCase()
354+
),
349355
onPressed: () {
350356
showLicensePage(
351357
context: context,
@@ -357,7 +363,11 @@ class AboutDialog extends StatelessWidget {
357363
},
358364
),
359365
TextButton(
360-
child: Text(MaterialLocalizations.of(context).closeButtonLabel),
366+
child: Text(
367+
themeData.useMaterial3
368+
? localizations.closeButtonLabel
369+
: localizations.closeButtonLabel.toUpperCase()
370+
),
361371
onPressed: () {
362372
Navigator.pop(context);
363373
},

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

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,11 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
479479
children: <Widget>[
480480
TextButton(
481481
onPressed: _handleCancel,
482-
child: Text(widget.cancelText ?? localizations.cancelButtonLabel),
482+
child: Text(widget.cancelText ?? (
483+
theme.useMaterial3
484+
? localizations.cancelButtonLabel
485+
: localizations.cancelButtonLabel.toUpperCase()
486+
)),
483487
),
484488
TextButton(
485489
onPressed: _handleOk,
@@ -571,7 +575,11 @@ class _DatePickerDialogState extends State<DatePickerDialog> with RestorationMix
571575
}
572576

573577
final Widget header = _DatePickerHeader(
574-
helpText: widget.helpText ?? localizations.datePickerHelpText,
578+
helpText: widget.helpText ?? (
579+
Theme.of(context).useMaterial3
580+
? localizations.datePickerHelpText
581+
: localizations.datePickerHelpText.toUpperCase()
582+
),
575583
titleText: dateText,
576584
titleStyle: dateStyle,
577585
orientation: orientation,
@@ -1348,8 +1356,16 @@ class _DateRangePickerDialogState extends State<DateRangePickerDialog> with Rest
13481356
onPressed: _handleEntryModeToggle,
13491357
)
13501358
: null,
1351-
confirmText: widget.saveText ?? localizations.saveButtonLabel,
1352-
helpText: widget.helpText ?? localizations.dateRangePickerHelpText,
1359+
confirmText: widget.saveText ?? (
1360+
Theme.of(context).useMaterial3
1361+
? localizations.saveButtonLabel
1362+
: localizations.saveButtonLabel.toUpperCase()
1363+
),
1364+
helpText: widget.helpText ?? (
1365+
Theme.of(context).useMaterial3
1366+
? localizations.dateRangePickerHelpText
1367+
: localizations.dateRangePickerHelpText.toUpperCase()
1368+
),
13531369
);
13541370
size = mediaQuery.size;
13551371
insetPadding = EdgeInsets.zero;
@@ -1406,8 +1422,16 @@ class _DateRangePickerDialogState extends State<DateRangePickerDialog> with Rest
14061422
)
14071423
: null,
14081424
confirmText: widget.confirmText ?? localizations.okButtonLabel,
1409-
cancelText: widget.cancelText ?? localizations.cancelButtonLabel,
1410-
helpText: widget.helpText ?? localizations.dateRangePickerHelpText,
1425+
cancelText: widget.cancelText ?? (
1426+
Theme.of(context).useMaterial3
1427+
? localizations.cancelButtonLabel
1428+
: localizations.cancelButtonLabel.toUpperCase()
1429+
),
1430+
helpText: widget.helpText ?? (
1431+
Theme.of(context).useMaterial3
1432+
? localizations.dateRangePickerHelpText
1433+
: localizations.dateRangePickerHelpText.toUpperCase()
1434+
),
14111435
);
14121436
final DialogTheme dialogTheme = Theme.of(context).dialogTheme;
14131437
size = orientation == Orientation.portrait ? _inputPortraitDialogSize : _inputRangeLandscapeDialogSize;
@@ -2613,7 +2637,11 @@ class _InputDateRangePickerDialog extends StatelessWidget {
26132637
: '';
26142638

26152639
final Widget header = _DatePickerHeader(
2616-
helpText: helpText ?? localizations.dateRangePickerHelpText,
2640+
helpText: helpText ?? (
2641+
Theme.of(context).useMaterial3
2642+
? localizations.dateRangePickerHelpText
2643+
: localizations.dateRangePickerHelpText.toUpperCase()
2644+
),
26172645
titleText: dateText,
26182646
titleSemanticsLabel: semanticDateText,
26192647
titleStyle: dateStyle,
@@ -2631,7 +2659,11 @@ class _InputDateRangePickerDialog extends StatelessWidget {
26312659
children: <Widget>[
26322660
TextButton(
26332661
onPressed: onCancel,
2634-
child: Text(cancelText ?? localizations.cancelButtonLabel),
2662+
child: Text(cancelText ?? (
2663+
theme.useMaterial3
2664+
? localizations.cancelButtonLabel
2665+
: localizations.cancelButtonLabel.toUpperCase()
2666+
)),
26352667
),
26362668
TextButton(
26372669
onPressed: onConfirm,

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -925,13 +925,13 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
925925
String get dateOutOfRangeLabel => 'Out of range.';
926926

927927
@override
928-
String get saveButtonLabel => 'SAVE';
928+
String get saveButtonLabel => 'Save';
929929

930930
@override
931-
String get datePickerHelpText => 'SELECT DATE';
931+
String get datePickerHelpText => 'Select date';
932932

933933
@override
934-
String get dateRangePickerHelpText => 'SELECT RANGE';
934+
String get dateRangePickerHelpText => 'Select range';
935935

936936
@override
937937
String get calendarModeButtonLabel => 'Switch to calendar';
@@ -940,10 +940,10 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
940940
String get inputDateModeButtonLabel => 'Switch to input';
941941

942942
@override
943-
String get timePickerDialHelpText => 'SELECT TIME';
943+
String get timePickerDialHelpText => 'Select time';
944944

945945
@override
946-
String get timePickerInputHelpText => 'ENTER TIME';
946+
String get timePickerInputHelpText => 'Enter time';
947947

948948
@override
949949
String get timePickerHourLabel => 'Hour';
@@ -1120,13 +1120,13 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
11201120
}
11211121

11221122
@override
1123-
String get cancelButtonLabel => 'CANCEL';
1123+
String get cancelButtonLabel => 'Cancel';
11241124

11251125
@override
1126-
String get closeButtonLabel => 'CLOSE';
1126+
String get closeButtonLabel => 'Close';
11271127

11281128
@override
1129-
String get continueButtonLabel => 'CONTINUE';
1129+
String get continueButtonLabel => 'Continue';
11301130

11311131
@override
11321132
String get copyButtonLabel => 'Copy';
@@ -1144,7 +1144,7 @@ class DefaultMaterialLocalizations implements MaterialLocalizations {
11441144
String get selectAllButtonLabel => 'Select all';
11451145

11461146
@override
1147-
String get viewLicensesButtonLabel => 'VIEW LICENSES';
1147+
String get viewLicensesButtonLabel => 'View licenses';
11481148

11491149
@override
11501150
String get anteMeridiemAbbreviation => 'AM';

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,11 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
525525
padding: const MaterialStatePropertyAll<EdgeInsetsGeometry>(buttonPadding),
526526
shape: const MaterialStatePropertyAll<OutlinedBorder>(buttonShape),
527527
),
528-
child: Text(localizations.continueButtonLabel),
528+
child: Text(
529+
themeData.useMaterial3
530+
? localizations.continueButtonLabel
531+
: localizations.continueButtonLabel.toUpperCase()
532+
),
529533
),
530534
Container(
531535
margin: const EdgeInsetsDirectional.only(start: 8.0),
@@ -536,7 +540,11 @@ class _StepperState extends State<Stepper> with TickerProviderStateMixin {
536540
padding: buttonPadding,
537541
shape: buttonShape,
538542
),
539-
child: Text(localizations.cancelButtonLabel),
543+
child: Text(
544+
themeData.useMaterial3
545+
? localizations.cancelButtonLabel
546+
: localizations.cancelButtonLabel.toUpperCase()
547+
),
540548
),
541549
),
542550
],

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,10 @@ class _TimePickerHeader extends StatelessWidget {
151151
final TimeOfDayFormat timeOfDayFormat = MaterialLocalizations.of(context).timeOfDayFormat(
152152
alwaysUse24HourFormat: MediaQuery.of(context).alwaysUse24HourFormat,
153153
);
154+
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
155+
final String timePickerDialHelpText = themeData.useMaterial3
156+
? localizations.timePickerDialHelpText
157+
: localizations.timePickerDialHelpText.toUpperCase();
154158

155159
final _TimePickerFragmentContext fragmentContext = _TimePickerFragmentContext(
156160
selectedTime: selectedTime,
@@ -255,7 +259,7 @@ class _TimePickerHeader extends StatelessWidget {
255259
children: <Widget>[
256260
const SizedBox(height: 16.0),
257261
Text(
258-
helpText ?? MaterialLocalizations.of(context).timePickerDialHelpText,
262+
helpText ?? timePickerDialHelpText,
259263
style: TimePickerTheme.of(context).helpTextStyle ?? themeData.textTheme.labelSmall,
260264
),
261265
controls,
@@ -1495,14 +1499,18 @@ class _TimePickerInputState extends State<_TimePickerInput> with RestorationMixi
14951499
final bool use24HourDials = hourFormat(of: timeOfDayFormat) != HourFormat.h;
14961500
final ThemeData theme = Theme.of(context);
14971501
final TextStyle hourMinuteStyle = TimePickerTheme.of(context).hourMinuteTextStyle ?? theme.textTheme.displayMedium!;
1502+
final MaterialLocalizations localizations = MaterialLocalizations.of(context);
1503+
final String timePickerInputHelpText = theme.useMaterial3
1504+
? localizations.timePickerInputHelpText
1505+
: localizations.timePickerInputHelpText.toUpperCase();
14981506

14991507
return Padding(
15001508
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 16.0),
15011509
child: Column(
15021510
crossAxisAlignment: CrossAxisAlignment.start,
15031511
children: <Widget>[
15041512
Text(
1505-
widget.helpText ?? MaterialLocalizations.of(context).timePickerInputHelpText,
1513+
widget.helpText ?? timePickerInputHelpText,
15061514
style: TimePickerTheme.of(context).helpTextStyle ?? theme.textTheme.labelSmall,
15071515
),
15081516
const SizedBox(height: 16.0),
@@ -2258,7 +2266,11 @@ class _TimePickerDialogState extends State<TimePickerDialog> with RestorationMix
22582266
children: <Widget>[
22592267
TextButton(
22602268
onPressed: _handleCancel,
2261-
child: Text(widget.cancelText ?? localizations.cancelButtonLabel),
2269+
child: Text(widget.cancelText ?? (
2270+
theme.useMaterial3
2271+
? localizations.cancelButtonLabel
2272+
: localizations.cancelButtonLabel.toUpperCase()
2273+
)),
22622274
),
22632275
TextButton(
22642276
onPressed: _handleOk,

packages/flutter/test/material/about_test.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,46 @@ void main() {
1515
LicenseRegistry.reset();
1616
});
1717

18+
testWidgets('Material3 has sentence case labels', (WidgetTester tester) async {
19+
await tester.pumpWidget(MaterialApp(
20+
theme: ThemeData(useMaterial3: true),
21+
builder: (BuildContext context, Widget? child) {
22+
return MediaQuery(
23+
// Display has a vertical hinge down the middle
24+
data: const MediaQueryData(
25+
size: Size(800, 600),
26+
displayFeatures: <DisplayFeature>[
27+
DisplayFeature(
28+
bounds: Rect.fromLTRB(390, 0, 410, 600),
29+
type: DisplayFeatureType.hinge,
30+
state: DisplayFeatureState.unknown,
31+
),
32+
],
33+
),
34+
child: child!,
35+
);
36+
},
37+
home: Builder(
38+
builder: (BuildContext context) => ElevatedButton(
39+
onPressed: () {
40+
showAboutDialog(
41+
context: context,
42+
useRootNavigator: false,
43+
applicationName: 'A',
44+
);
45+
},
46+
child: const Text('Show About Dialog'),
47+
),
48+
),
49+
));
50+
51+
// Open the dialog.
52+
await tester.tap(find.byType(ElevatedButton));
53+
await tester.pumpAndSettle();
54+
expect(find.text('Close'), findsOneWidget);
55+
expect(find.text('View licenses'), findsOneWidget);
56+
});
57+
1858
testWidgets('AboutListTile control test', (WidgetTester tester) async {
1959
const FlutterLogo logo = FlutterLogo();
2060

packages/flutter/test/material/date_picker_test.dart

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,11 @@ void main() {
6262
WidgetTester tester,
6363
Future<void> Function(Future<DateTime?> date) callback, {
6464
TextDirection textDirection = TextDirection.ltr,
65+
bool useMaterial3 = false,
6566
}) async {
6667
late BuildContext buttonContext;
6768
await tester.pumpWidget(MaterialApp(
69+
theme: ThemeData(useMaterial3: useMaterial3),
6870
home: Material(
6971
child: Builder(
7072
builder: (BuildContext context) {
@@ -112,6 +114,11 @@ void main() {
112114
}
113115

114116
group('showDatePicker Dialog', () {
117+
testWidgets('Material3 uses sentence case labels', (WidgetTester tester) async {
118+
await prepareDatePicker(tester, (Future<DateTime?> date) async {
119+
expect(find.text('Select date'), findsOneWidget);
120+
}, useMaterial3: true);
121+
});
115122
testWidgets('Cancel, confirm, and help text is used', (WidgetTester tester) async {
116123
cancelText = 'nope';
117124
confirmText = 'yep';

packages/flutter/test/material/date_range_picker_test.dart

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ void main() {
5656
WidgetTester tester,
5757
Future<void> Function(Future<DateTimeRange?> date) callback, {
5858
TextDirection textDirection = TextDirection.ltr,
59+
bool useMaterial3 = false,
5960
}) async {
6061
late BuildContext buttonContext;
6162
await tester.pumpWidget(MaterialApp(
63+
theme: ThemeData(useMaterial3: useMaterial3),
6264
home: Material(
6365
child: Builder(
6466
builder: (BuildContext context) {
@@ -115,6 +117,13 @@ void main() {
115117
});
116118
});
117119

120+
testWidgets('Material3 has sentence case labels', (WidgetTester tester) async {
121+
await preparePicker(tester, (Future<DateTimeRange?> range) async {
122+
expect(find.text('Save'), findsOneWidget);
123+
expect(find.text('Select range'), findsOneWidget);
124+
}, useMaterial3: true);
125+
});
126+
118127
testWidgets('Initial date is the default', (WidgetTester tester) async {
119128
await preparePicker(tester, (Future<DateTimeRange?> range) async {
120129
await tester.tap(find.text('SAVE'));

0 commit comments

Comments
 (0)