Unverified Commit 57aa4902 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Migrate NavigationRail to Material 3. (#99171)

parent 9291c8ba
......@@ -20,6 +20,7 @@ import 'dart:io';
import 'package:gen_defaults/dialog_template.dart';
import 'package:gen_defaults/fab_template.dart';
import 'package:gen_defaults/navigation_bar_template.dart';
import 'package:gen_defaults/navigation_rail_template.dart';
import 'package:gen_defaults/typography_template.dart';
Map<String, dynamic> _readTokenFile(String fileName) {
......@@ -45,6 +46,7 @@ Future<void> main(List<String> args) async {
'input_chip.json',
'motion.json',
'navigation_bar.json',
'navigation_rail.json',
'outlined_card.json',
'palette.json',
'shape.json',
......@@ -70,6 +72,7 @@ Future<void> main(List<String> args) async {
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
NavigationBarTemplate('$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationRailTemplate('$materialLib/navigation_rail.dart', tokens).updateFile();
TypographyTemplate('$materialLib/typography.dart', tokens).updateFile();
DialogTemplate('$materialLib/dialog.dart', tokens).updateFile();
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'template.dart';
class NavigationRailTemplate extends TokenTemplate {
const NavigationRailTemplate(String fileName, Map<String, dynamic> tokens) : super(fileName, tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _TokenDefaultsM3 extends NavigationRailThemeData {
_TokenDefaultsM3(BuildContext context)
: _theme = Theme.of(context),
_colors = Theme.of(context).colorScheme,
super(
elevation: ${elevation("md.comp.navigation-rail.container")},
groupAlignment: -1,
labelType: NavigationRailLabelType.none,
useIndicator: true,
minWidth: ${tokens["md.comp.navigation-rail.container.width"]},
minExtendedWidth: 256,
);
final ThemeData _theme;
final ColorScheme _colors;
@override Color? get backgroundColor => _colors.${color("md.comp.navigation-rail.container")};
@override TextStyle? get unselectedLabelTextStyle {
return _theme.textTheme.${textStyle("md.comp.navigation-rail.label-text")}!.copyWith(color: _colors.${color("md.comp.navigation-rail.inactive.focus.label-text")});
}
@override TextStyle? get selectedLabelTextStyle {
return _theme.textTheme.${textStyle("md.comp.navigation-rail.label-text")}!.copyWith(color: _colors.${color("md.comp.navigation-rail.active.focus.label-text")});
}
@override IconThemeData? get unselectedIconTheme {
return IconThemeData(
size: ${tokens["md.comp.navigation-rail.icon.size"]},
color: _colors.${color("md.comp.navigation-rail.inactive.icon")},
);
}
@override IconThemeData? get selectedIconTheme {
return IconThemeData(
size: ${tokens["md.comp.navigation-rail.icon.size"]},
color: _colors.${color("md.comp.navigation-rail.active.icon")},
);
}
@override Color? get indicatorColor => _colors.${color("md.comp.navigation-rail.active-indicator")};
}
''';
}
......@@ -46,6 +46,8 @@ class NavigationRailThemeData with Diagnosticable {
this.labelType,
this.useIndicator,
this.indicatorColor,
this.minWidth,
this.minExtendedWidth,
});
/// Color to be used for the [NavigationRail]'s background.
......@@ -86,6 +88,14 @@ class NavigationRailThemeData with Diagnosticable {
/// when [useIndicator] is true.
final Color? indicatorColor;
/// Overrides the default value of [NavigationRail]'s minimum width when it
/// is not extended.
final double? minWidth;
/// Overrides the default value of [NavigationRail]'s minimum width when it
/// is extended.
final double? minExtendedWidth;
/// Creates a copy of this object with the given fields replaced with the
/// new values.
NavigationRailThemeData copyWith({
......@@ -99,6 +109,8 @@ class NavigationRailThemeData with Diagnosticable {
NavigationRailLabelType? labelType,
bool? useIndicator,
Color? indicatorColor,
double? minWidth,
double? minExtendedWidth,
}) {
return NavigationRailThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
......@@ -111,6 +123,8 @@ class NavigationRailThemeData with Diagnosticable {
labelType: labelType ?? this.labelType,
useIndicator: useIndicator ?? this.useIndicator,
indicatorColor: indicatorColor ?? this.indicatorColor,
minWidth: minWidth ?? this.minWidth,
minExtendedWidth: minExtendedWidth ?? this.minExtendedWidth,
);
}
......@@ -134,6 +148,9 @@ class NavigationRailThemeData with Diagnosticable {
labelType: t < 0.5 ? a?.labelType : b?.labelType,
useIndicator: t < 0.5 ? a?.useIndicator : b?.useIndicator,
indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t),
minWidth: lerpDouble(a?.minWidth, b?.minWidth, t),
minExtendedWidth: lerpDouble(a?.minExtendedWidth, b?.minExtendedWidth, t),
);
}
......@@ -149,6 +166,8 @@ class NavigationRailThemeData with Diagnosticable {
labelType,
useIndicator,
indicatorColor,
minWidth,
minExtendedWidth,
);
@override
......@@ -167,7 +186,9 @@ class NavigationRailThemeData with Diagnosticable {
&& other.groupAlignment == groupAlignment
&& other.labelType == labelType
&& other.useIndicator == useIndicator
&& other.indicatorColor == indicatorColor;
&& other.indicatorColor == indicatorColor
&& other.minWidth == minWidth
&& other.minExtendedWidth == minExtendedWidth;
}
@override
......@@ -185,6 +206,8 @@ class NavigationRailThemeData with Diagnosticable {
properties.add(DiagnosticsProperty<NavigationRailLabelType>('labelType', labelType, defaultValue: defaultData.labelType));
properties.add(DiagnosticsProperty<bool>('useIndicator', useIndicator, defaultValue: defaultData.useIndicator));
properties.add(ColorProperty('indicatorColor', indicatorColor, defaultValue: defaultData.indicatorColor));
properties.add(DoubleProperty('minWidth', minWidth, defaultValue: defaultData.minWidth));
properties.add(DoubleProperty('minExtendedWidth', minExtendedWidth, defaultValue: defaultData.minExtendedWidth));
}
}
......
......@@ -1087,8 +1087,12 @@ class ThemeData with Diagnosticable {
/// start using new colors, typography and other features of Material 3.
/// If false, they will use the Material 2 look and feel.
///
/// If true, the default Typography will be [Typography.material2021],
/// otherwise it will default to [Typography.material2014].
/// If a [ThemeData] is constructed with [useMaterial3] set to true,
/// the default [typography] will be [Typography.material2021],
/// otherwise it will be [Typography.material2014].
///
/// However, just copying a [ThemeData] with [useMaterial3] set to true will
/// not change the typography of the resulting ThemeData.
///
/// During the migration to Material 3, turning this on may yield
/// inconsistent look and feel in your app. Some components will be migrated
......@@ -1102,10 +1106,11 @@ class ThemeData with Diagnosticable {
///
/// Components that have been migrated to Material 3 are:
///
/// * [AlertDialog]
/// * [Dialog]
/// * [FloatingActionButton]
/// * [NavigationBar]
/// * [Dialog]
/// * [AlertDialog]
/// * [NavigationRail]
///
/// See also:
///
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -13,8 +13,10 @@ void main() {
});
testWidgets('Default values are used when no NavigationRail or NavigationRailThemeData properties are specified', (WidgetTester tester) async {
// Material 3 defaults
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light().copyWith(useMaterial3: true),
home: Scaffold(
body: NavigationRail(
selectedIndex: 0,
......@@ -26,6 +28,37 @@ void main() {
expect(_railMaterial(tester).color, ThemeData().colorScheme.surface);
expect(_railMaterial(tester).elevation, 0);
expect(_destinationSize(tester).width, 80.0);
expect(_selectedIconTheme(tester).size, 24.0);
expect(_selectedIconTheme(tester).color, ThemeData().colorScheme.onSecondaryContainer);
expect(_selectedIconTheme(tester).opacity, null);
expect(_unselectedIconTheme(tester).size, 24.0);
expect(_unselectedIconTheme(tester).color, ThemeData().colorScheme.onSurface);
expect(_unselectedIconTheme(tester).opacity, null);
expect(_selectedLabelStyle(tester).fontSize, 14.0);
expect(_unselectedLabelStyle(tester).fontSize, 14.0);
expect(_destinationsAlign(tester).alignment, Alignment.topCenter);
expect(_labelType(tester), NavigationRailLabelType.none);
expect(find.byType(NavigationIndicator), findsWidgets);
});
testWidgets('Default values are used when no NavigationRail or NavigationRailThemeData properties are specified (Material 2)', (WidgetTester tester) async {
// This test can be removed when `useMaterial3` is deprecated.
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.light().copyWith(useMaterial3: false),
home: Scaffold(
body: NavigationRail(
selectedIndex: 0,
destinations: _destinations(),
),
),
),
);
expect(_railMaterial(tester).color, ThemeData().colorScheme.surface);
expect(_railMaterial(tester).elevation, 0);
expect(_destinationSize(tester).width, 72.0);
expect(_selectedIconTheme(tester).size, 24.0);
expect(_selectedIconTheme(tester).color, ThemeData().colorScheme.primary);
expect(_selectedIconTheme(tester).opacity, 1.0);
......@@ -308,6 +341,16 @@ TextStyle _unselectedLabelStyle(WidgetTester tester) {
).text.style!;
}
Size _destinationSize(WidgetTester tester) {
return tester.getSize(
find.ancestor(
of: find.byIcon(Icons.favorite),
matching: find.byType(Material),
)
.first
);
}
Align _destinationsAlign(WidgetTester tester) {
// The first Expanded widget is the one within the main Column for the rail
// content.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment