Unverified Commit 33ed6a35 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Fixing elevation issues with Material 3 (#110624)

* Added support for surfaceTintColor and shadowColor to the Dialog widgets.
* Updated the defaults for Material.shadowColor and Material.surfaceTint to allow turning off the features with a transparent color.
* Added support for shadowColor and surfaceTintColor for Drawer widget.
parent 1b4b480a
...@@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData { ...@@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")}; Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override @override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")}; Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override @override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")}; Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override @override
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")}; Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
......
...@@ -34,7 +34,10 @@ class _${blockName}DefaultsM3 extends AppBarTheme { ...@@ -34,7 +34,10 @@ class _${blockName}DefaultsM3 extends AppBarTheme {
Color? get foregroundColor => ${color('md.comp.top-app-bar.small.headline.color')}; Color? get foregroundColor => ${color('md.comp.top-app-bar.small.headline.color')};
@override @override
Color? get surfaceTintColor => ${componentColor('md.comp.top-app-bar.small.container.surface-tint-layer')}; Color? get shadowColor => ${colorOrTransparent('md.comp.top-app-bar.small.container.shadow-color')};
@override
Color? get surfaceTintColor => ${colorOrTransparent('md.comp.top-app-bar.small.container.surface-tint-layer.color')};
@override @override
IconThemeData? get iconTheme => IconThemeData( IconThemeData? get iconTheme => IconThemeData(
......
...@@ -24,7 +24,7 @@ class ButtonTemplate extends TokenTemplate { ...@@ -24,7 +24,7 @@ class ButtonTemplate extends TokenTemplate {
} }
return ''' return '''
ButtonStyleButton.allOrNull<Color>(Colors.transparent)'''; const MaterialStatePropertyAll<Color>(Colors.transparent)''';
} }
String _elevation() { String _elevation() {
...@@ -49,7 +49,15 @@ class ButtonTemplate extends TokenTemplate { ...@@ -49,7 +49,15 @@ class ButtonTemplate extends TokenTemplate {
} }
return ''' return '''
ButtonStyleButton.allOrNull<double>(0.0)'''; const MaterialStatePropertyAll<double>(0.0)''';
}
String _elevationColor(String token) {
if (tokens.containsKey(token)) {
return 'MaterialStatePropertyAll<Color>(${color(token)})';
} else {
return 'const MaterialStatePropertyAll<Color>(Colors.transparent)';
}
} }
@override @override
...@@ -96,34 +104,30 @@ class _${blockName}DefaultsM3 extends ButtonStyle { ...@@ -96,34 +104,30 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
return null; return null;
}); });
${tokens.containsKey("$tokenGroup.container.shadow-color") ? '''
@override @override
MaterialStateProperty<Color>? get shadowColor => MaterialStateProperty<Color>? get shadowColor =>
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.shadow-color")});''' : ''' ${_elevationColor("$tokenGroup.container.shadow-color")};
// No default shadow color'''}
${tokens.containsKey("$tokenGroup.container.surface-tint-layer.color") ? '''
@override @override
MaterialStateProperty<Color>? get surfaceTintColor => MaterialStateProperty<Color>? get surfaceTintColor =>
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.surface-tint-layer.color")});''' : ''' ${_elevationColor("$tokenGroup.container.surface-tint-layer.color")};
// No default surface tint color'''}
@override @override
MaterialStateProperty<double>? get elevation =>${_elevation()}; MaterialStateProperty<double>? get elevation =>${_elevation()};
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, ${tokens["$tokenGroup.container.height"]})); const MaterialStatePropertyAll<Size>(Size(64.0, ${tokens["$tokenGroup.container.height"]}));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
${tokens.containsKey("$tokenGroup.outline.color") ? ''' ${tokens.containsKey("$tokenGroup.outline.color") ? '''
@override @override
...@@ -138,7 +142,7 @@ ${tokens.containsKey("$tokenGroup.outline.color") ? ''' ...@@ -138,7 +142,7 @@ ${tokens.containsKey("$tokenGroup.outline.color") ? '''
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("$tokenGroup.container")}); const MaterialStatePropertyAll<OutlinedBorder>(${shape("$tokenGroup.container", '')});
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -25,10 +25,10 @@ class _${blockName}DefaultsM3 extends CardTheme { ...@@ -25,10 +25,10 @@ class _${blockName}DefaultsM3 extends CardTheme {
Color? get color => ${componentColor("md.comp.elevated-card.container")}; Color? get color => ${componentColor("md.comp.elevated-card.container")};
@override @override
Color? get shadowColor => ${color("md.comp.elevated-card.container.shadow-color")}; Color? get shadowColor => ${colorOrTransparent("md.comp.elevated-card.container.shadow-color")};
@override @override
Color? get surfaceTintColor => ${color("md.comp.elevated-card.container.surface-tint-layer.color")}; Color? get surfaceTintColor => ${colorOrTransparent("md.comp.elevated-card.container.surface-tint-layer.color")};
} }
'''; ''';
} }
...@@ -27,9 +27,14 @@ class _${blockName}DefaultsM3 extends DialogTheme { ...@@ -27,9 +27,14 @@ class _${blockName}DefaultsM3 extends DialogTheme {
@override @override
Color? get iconColor => _colors.secondary; Color? get iconColor => _colors.secondary;
// TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160
@override @override
Color? get backgroundColor => ElevationOverlay.colorWithOverlay(${componentColor("md.comp.dialog.container")}, _colors.primary, ${elevation("md.comp.dialog.container")}); Color? get backgroundColor => ${componentColor("md.comp.dialog.container")};
@override
Color? get shadowColor => ${colorOrTransparent("md.comp.dialog.container.shadow-color")};
@override
Color? get surfaceTintColor => ${colorOrTransparent("md.comp.dialog.container.surface-tint-layer.color")};
@override @override
TextStyle? get titleTextStyle => ${textStyle("md.comp.dialog.headline")}; TextStyle? get titleTextStyle => ${textStyle("md.comp.dialog.headline")};
......
...@@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData { ...@@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")}; Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override @override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")}; Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override @override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")}; Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override @override
Color? get selectedColor => isEnabled Color? get selectedColor => isEnabled
......
...@@ -9,6 +9,15 @@ class IconButtonTemplate extends TokenTemplate { ...@@ -9,6 +9,15 @@ class IconButtonTemplate extends TokenTemplate {
super.colorSchemePrefix = '_colors.', super.colorSchemePrefix = '_colors.',
}); });
String _elevationColor(String token) {
if (tokens.containsKey(token)) {
return 'MaterialStatePropertyAll<Color>(${color(token)})';
} else {
return 'const MaterialStatePropertyAll<Color>(Colors.transparent)';
}
}
@override @override
String generate() => ''' String generate() => '''
class _${blockName}DefaultsM3 extends ButtonStyle { class _${blockName}DefaultsM3 extends ButtonStyle {
...@@ -26,7 +35,7 @@ class _${blockName}DefaultsM3 extends ButtonStyle { ...@@ -26,7 +35,7 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color?>? get backgroundColor => MaterialStateProperty<Color?>? get backgroundColor =>
ButtonStyleButton.allOrNull<Color>(Colors.transparent); const MaterialStatePropertyAll<Color?>(Colors.transparent);
@override @override
MaterialStateProperty<Color?>? get foregroundColor => MaterialStateProperty<Color?>? get foregroundColor =>
...@@ -66,37 +75,41 @@ class _${blockName}DefaultsM3 extends ButtonStyle { ...@@ -66,37 +75,41 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
return null; return null;
}); });
// No default shadow color @override
MaterialStateProperty<double>? get elevation =>
const MaterialStatePropertyAll<double>(0.0);
// No default surface tint color @override
MaterialStateProperty<Color>? get shadowColor =>
${_elevationColor("md.comp.icon-button.container.shadow-color")};
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<Color>? get surfaceTintColor =>
ButtonStyleButton.allOrNull<double>(0.0); ${_elevationColor("md.comp.icon-button.container.surface-tint-layer.color")};
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0)); const MaterialStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.all(8.0));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(${tokens["md.comp.icon-button.state-layer.size"]}, ${tokens["md.comp.icon-button.state-layer.size"]})); const MaterialStatePropertyAll<Size>(Size(${tokens["md.comp.icon-button.state-layer.size"]}, ${tokens["md.comp.icon-button.state-layer.size"]}));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
@override @override
MaterialStateProperty<double>? get iconSize => MaterialStateProperty<double>? get iconSize =>
ButtonStyleButton.allOrNull<double>(${tokens["md.comp.icon-button.icon.size"]}); const MaterialStatePropertyAll<double>(${tokens["md.comp.icon-button.icon.size"]});
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("md.comp.icon-button.state-layer")}); const MaterialStatePropertyAll<OutlinedBorder>(${shape("md.comp.icon-button.state-layer", "")});
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -30,10 +30,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData { ...@@ -30,10 +30,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")}; Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override @override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")}; Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override @override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")}; Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override @override
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")}; Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
......
...@@ -26,7 +26,9 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData { ...@@ -26,7 +26,9 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData {
@override Color? get backgroundColor => ${componentColor("md.comp.navigation-bar.container")}; @override Color? get backgroundColor => ${componentColor("md.comp.navigation-bar.container")};
@override Color? get surfaceTintColor => ${color("md.comp.navigation-bar.container.surface-tint-layer.color")}; @override Color? get shadowColor => ${colorOrTransparent("md.comp.navigation-bar.container.shadow-color")};
@override Color? get surfaceTintColor => ${colorOrTransparent("md.comp.navigation-bar.container.surface-tint-layer.color")};
@override MaterialStateProperty<IconThemeData?>? get iconTheme { @override MaterialStateProperty<IconThemeData?>? get iconTheme {
return MaterialStateProperty.resolveWith((Set<MaterialState> states) { return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
......
...@@ -97,16 +97,28 @@ abstract class TokenTemplate { ...@@ -97,16 +97,28 @@ abstract class TokenTemplate {
/// If there is a value for the given token, this will return /// If there is a value for the given token, this will return
/// the value prepended with [colorSchemePrefix]. /// the value prepended with [colorSchemePrefix].
/// ///
/// Otherwise it will return 'null'. /// Otherwise it will return [defaultValue].
/// ///
/// See also: /// See also:
/// * [componentColor], that provides support for an optional opacity. /// * [componentColor], that provides support for an optional opacity.
String color(String colorToken) { String color(String colorToken, [String defaultValue = 'null']) {
return tokens.containsKey(colorToken) return tokens.containsKey(colorToken)
? '$colorSchemePrefix${tokens[colorToken]}' ? '$colorSchemePrefix${tokens[colorToken]}'
: 'null'; : defaultValue;
} }
/// Generate a [ColorScheme] color name for the given token or a transparent
/// color if there is no value for the token.
///
/// If there is a value for the given token, this will return
/// the value prepended with [colorSchemePrefix].
///
/// Otherwise it will return 'Colors.transparent'.
///
/// See also:
/// * [componentColor], that provides support for an optional opacity.
String? colorOrTransparent(String token) => color(token, 'Colors.transparent');
/// Generate a [ColorScheme] color name for the given component's color /// Generate a [ColorScheme] color name for the given component's color
/// with opacity if available. /// with opacity if available.
/// ///
...@@ -154,18 +166,18 @@ abstract class TokenTemplate { ...@@ -154,18 +166,18 @@ abstract class TokenTemplate {
/// Currently supports family: /// Currently supports family:
/// - "SHAPE_FAMILY_ROUNDED_CORNERS" which maps to [RoundedRectangleBorder]. /// - "SHAPE_FAMILY_ROUNDED_CORNERS" which maps to [RoundedRectangleBorder].
/// - "SHAPE_FAMILY_CIRCULAR" which maps to a [StadiumBorder]. /// - "SHAPE_FAMILY_CIRCULAR" which maps to a [StadiumBorder].
String shape(String componentToken) { String shape(String componentToken, [String prefix = 'const ']) {
final Map<String, dynamic> shape = tokens[tokens['$componentToken.shape']!]! as Map<String, dynamic>; final Map<String, dynamic> shape = tokens[tokens['$componentToken.shape']!]! as Map<String, dynamic>;
switch (shape['family']) { switch (shape['family']) {
case 'SHAPE_FAMILY_ROUNDED_CORNERS': case 'SHAPE_FAMILY_ROUNDED_CORNERS':
return 'const RoundedRectangleBorder(borderRadius: ' return '${prefix}RoundedRectangleBorder(borderRadius: '
'BorderRadius.only(' 'BorderRadius.only('
'topLeft: Radius.circular(${shape['topLeft']}), ' 'topLeft: Radius.circular(${shape['topLeft']}), '
'topRight: Radius.circular(${shape['topRight']}), ' 'topRight: Radius.circular(${shape['topRight']}), '
'bottomLeft: Radius.circular(${shape['bottomLeft']}), ' 'bottomLeft: Radius.circular(${shape['bottomLeft']}), '
'bottomRight: Radius.circular(${shape['bottomRight']})))'; 'bottomRight: Radius.circular(${shape['bottomRight']})))';
case 'SHAPE_FAMILY_CIRCULAR': case 'SHAPE_FAMILY_CIRCULAR':
return 'const StadiumBorder()'; return '${prefix}StadiumBorder()';
} }
print('Unsupported shape family type: ${shape['family']} for $componentToken'); print('Unsupported shape family type: ${shape['family']} for $componentToken');
return ''; return '';
......
...@@ -16,7 +16,7 @@ void main() { ...@@ -16,7 +16,7 @@ void main() {
expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget); expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget);
Material appbarMaterial = _getAppBarMaterial(tester); Material appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, null); expect(appbarMaterial.shadowColor, Colors.transparent);
expect(appbarMaterial.elevation, 0); expect(appbarMaterial.elevation, 0);
await tester.drag(find.text('Item 4'), _kOffset, touchSlopY: 0, warnIfMissed: false); await tester.drag(find.text('Item 4'), _kOffset, touchSlopY: 0, warnIfMissed: false);
......
...@@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart'; ...@@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
import 'chip.dart'; import 'chip.dart';
import 'chip_theme.dart'; import 'chip_theme.dart';
import 'colors.dart';
import 'debug.dart'; import 'debug.dart';
import 'theme.dart'; import 'theme.dart';
import 'theme_data.dart'; import 'theme_data.dart';
...@@ -196,10 +197,10 @@ class _ActionChipDefaultsM3 extends ChipThemeData { ...@@ -196,10 +197,10 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
Color? get backgroundColor => null; Color? get backgroundColor => null;
@override @override
Color? get shadowColor => null; Color? get shadowColor => Colors.transparent;
@override @override
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint; Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@override @override
Color? get selectedColor => null; Color? get selectedColor => null;
......
...@@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart'; ...@@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart';
import 'app_bar_theme.dart'; import 'app_bar_theme.dart';
import 'back_button.dart'; import 'back_button.dart';
import 'color_scheme.dart'; import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart'; import 'constants.dart';
import 'debug.dart'; import 'debug.dart';
import 'flexible_space_bar.dart'; import 'flexible_space_bar.dart';
...@@ -2370,6 +2371,9 @@ class _AppBarDefaultsM3 extends AppBarTheme { ...@@ -2370,6 +2371,9 @@ class _AppBarDefaultsM3 extends AppBarTheme {
@override @override
Color? get foregroundColor => _colors.onSurface; Color? get foregroundColor => _colors.onSurface;
@override
Color? get shadowColor => Colors.transparent;
@override @override
Color? get surfaceTintColor => _colors.surfaceTint; Color? get surfaceTintColor => _colors.surfaceTint;
......
...@@ -213,7 +213,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData { ...@@ -213,7 +213,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
Color? get shadowColor => Theme.of(context).colorScheme.shadow; Color? get shadowColor => Theme.of(context).colorScheme.shadow;
@override @override
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint; Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@override @override
Color? get selectedColor => isEnabled Color? get selectedColor => isEnabled
......
...@@ -11,7 +11,6 @@ import 'color_scheme.dart'; ...@@ -11,7 +11,6 @@ import 'color_scheme.dart';
import 'colors.dart'; import 'colors.dart';
import 'debug.dart'; import 'debug.dart';
import 'dialog_theme.dart'; import 'dialog_theme.dart';
import 'elevation_overlay.dart';
import 'ink_well.dart'; import 'ink_well.dart';
import 'material.dart'; import 'material.dart';
import 'material_localizations.dart'; import 'material_localizations.dart';
...@@ -46,6 +45,8 @@ class Dialog extends StatelessWidget { ...@@ -46,6 +45,8 @@ class Dialog extends StatelessWidget {
super.key, super.key,
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.insetAnimationDuration = const Duration(milliseconds: 100), this.insetAnimationDuration = const Duration(milliseconds: 100),
this.insetAnimationCurve = Curves.decelerate, this.insetAnimationCurve = Curves.decelerate,
this.insetPadding = _defaultInsetPadding, this.insetPadding = _defaultInsetPadding,
...@@ -53,7 +54,8 @@ class Dialog extends StatelessWidget { ...@@ -53,7 +54,8 @@ class Dialog extends StatelessWidget {
this.shape, this.shape,
this.alignment, this.alignment,
this.child, this.child,
}) : assert(clipBehavior != null); }) : assert(clipBehavior != null),
assert(elevation == null || elevation >= 0.0);
/// {@template flutter.material.dialog.backgroundColor} /// {@template flutter.material.dialog.backgroundColor}
/// The background color of the surface of this [Dialog]. /// The background color of the surface of this [Dialog].
...@@ -67,12 +69,63 @@ class Dialog extends StatelessWidget { ...@@ -67,12 +69,63 @@ class Dialog extends StatelessWidget {
/// {@template flutter.material.dialog.elevation} /// {@template flutter.material.dialog.elevation}
/// The z-coordinate of this [Dialog]. /// The z-coordinate of this [Dialog].
/// ///
/// If null then [DialogTheme.elevation] is used, and if that's null then the /// Controls how far above the parent the dialog will appear. Elevation is
/// dialog's elevation is 24.0. /// represented by a drop shadow if [shadowColor] is non null,
/// and a surface tint overlay on the background color if [surfaceTintColor] is
/// non null.
///
/// If null then [DialogTheme.elevation] is used, and if that is null then
/// the elevation will match the Material Design specification for Dialogs.
///
/// See also:
/// * [Material.elevation], which describes how [elevation] effects the
/// drop shadow or surface tint overlay.
/// * [shadowColor], color of the drop shadow used to indicate the elevation.
/// * [surfaceTintColor], color of an overlay on top of the background
/// color used to indicate the elevation.
/// * <https://m3.material.io/components/dialogs/overview>, the Material
/// Design specification for dialogs.
/// {@endtemplate} /// {@endtemplate}
/// {@macro flutter.material.material.elevation}
final double? elevation; final double? elevation;
/// {@template flutter.material.dialog.shadowColor}
/// The color used to paint a drop shadow under the dialog's [Material],
/// which reflects the dialog's [elevation].
///
/// If null and [ThemeData.useMaterial3] is true then no drop shadow will
/// be rendered.
///
/// If null and [ThemeData.useMaterial3] is false then it will default to
/// [ThemeData.shadowColor].
///
/// See also:
/// * [Material.shadowColor], which describes how the drop shadow is painted.
/// * [elevation], which affects how the drop shadow is painted.
/// * [surfaceTintColor], which can be used to indicate elevation through
/// tinting the background color.
/// {@endtemplate}
final Color? shadowColor;
/// {@template flutter.material.dialog.surfaceTintColor}
/// The color used as a surface tint overlay on the dialog's background color,
/// which reflects the dialog's [elevation].
///
/// If [ThemeData.useMaterial3] is false property has no effect.
///
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
/// [ColorScheme.surfaceTint] will be used.
///
/// To disable this feature, set [surfaceTintColor] to [Colors.transparent].
///
/// See also:
/// * [Material.surfaceTintColor], which describes how the surface tint will
/// be applied to the background color of the dialog.
/// * [elevation], which affects the opacity of the surface tint.
/// * [shadowColor], which can be used to indicate elevation through
/// a drop shadow.
/// {@endtemplate}
final Color? surfaceTintColor;
/// {@template flutter.material.dialog.insetAnimationDuration} /// {@template flutter.material.dialog.insetAnimationDuration}
/// The duration of the animation to show when the system keyboard intrudes /// The duration of the animation to show when the system keyboard intrudes
/// into the space that the dialog is placed in. /// into the space that the dialog is placed in.
...@@ -155,6 +208,8 @@ class Dialog extends StatelessWidget { ...@@ -155,6 +208,8 @@ class Dialog extends StatelessWidget {
child: Material( child: Material(
color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor, color: backgroundColor ?? dialogTheme.backgroundColor ?? Theme.of(context).dialogBackgroundColor,
elevation: elevation ?? dialogTheme.elevation ?? defaults.elevation!, elevation: elevation ?? dialogTheme.elevation ?? defaults.elevation!,
shadowColor: shadowColor ?? dialogTheme.shadowColor ?? defaults.shadowColor,
surfaceTintColor: surfaceTintColor ?? dialogTheme.surfaceTintColor ?? defaults.surfaceTintColor,
shape: shape ?? dialogTheme.shape ?? defaults.shape!, shape: shape ?? dialogTheme.shape ?? defaults.shape!,
type: MaterialType.card, type: MaterialType.card,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
...@@ -280,6 +335,8 @@ class AlertDialog extends StatelessWidget { ...@@ -280,6 +335,8 @@ class AlertDialog extends StatelessWidget {
this.buttonPadding, this.buttonPadding,
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.semanticLabel, this.semanticLabel,
this.insetPadding = _defaultInsetPadding, this.insetPadding = _defaultInsetPadding,
this.clipBehavior = Clip.none, this.clipBehavior = Clip.none,
...@@ -478,9 +535,14 @@ class AlertDialog extends StatelessWidget { ...@@ -478,9 +535,14 @@ class AlertDialog extends StatelessWidget {
final Color? backgroundColor; final Color? backgroundColor;
/// {@macro flutter.material.dialog.elevation} /// {@macro flutter.material.dialog.elevation}
/// {@macro flutter.material.material.elevation}
final double? elevation; final double? elevation;
/// {@macro flutter.material.dialog.shadowColor}
final Color? shadowColor;
/// {@macro flutter.material.dialog.surfaceTintColor}
final Color? surfaceTintColor;
/// The semantic label of the dialog used by accessibility frameworks to /// The semantic label of the dialog used by accessibility frameworks to
/// announce screen transitions when the dialog is opened and closed. /// announce screen transitions when the dialog is opened and closed.
/// ///
...@@ -695,6 +757,8 @@ class AlertDialog extends StatelessWidget { ...@@ -695,6 +757,8 @@ class AlertDialog extends StatelessWidget {
return Dialog( return Dialog(
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
insetPadding: insetPadding, insetPadding: insetPadding,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
shape: shape, shape: shape,
...@@ -860,6 +924,8 @@ class SimpleDialog extends StatelessWidget { ...@@ -860,6 +924,8 @@ class SimpleDialog extends StatelessWidget {
this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0), this.contentPadding = const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 16.0),
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.semanticLabel, this.semanticLabel,
this.insetPadding = _defaultInsetPadding, this.insetPadding = _defaultInsetPadding,
this.clipBehavior = Clip.none, this.clipBehavior = Clip.none,
...@@ -915,9 +981,14 @@ class SimpleDialog extends StatelessWidget { ...@@ -915,9 +981,14 @@ class SimpleDialog extends StatelessWidget {
final Color? backgroundColor; final Color? backgroundColor;
/// {@macro flutter.material.dialog.elevation} /// {@macro flutter.material.dialog.elevation}
/// {@macro flutter.material.material.elevation}
final double? elevation; final double? elevation;
/// {@macro flutter.material.dialog.shadowColor}
final Color? shadowColor;
/// {@macro flutter.material.dialog.surfaceTintColor}
final Color? surfaceTintColor;
/// The semantic label of the dialog used by accessibility frameworks to /// The semantic label of the dialog used by accessibility frameworks to
/// announce screen transitions when the dialog is opened and closed. /// announce screen transitions when the dialog is opened and closed.
/// ///
...@@ -1031,6 +1102,8 @@ class SimpleDialog extends StatelessWidget { ...@@ -1031,6 +1102,8 @@ class SimpleDialog extends StatelessWidget {
return Dialog( return Dialog(
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
insetPadding: insetPadding, insetPadding: insetPadding,
clipBehavior: clipBehavior, clipBehavior: clipBehavior,
shape: shape, shape: shape,
...@@ -1296,6 +1369,9 @@ class _DialogDefaultsM2 extends DialogTheme { ...@@ -1296,6 +1369,9 @@ class _DialogDefaultsM2 extends DialogTheme {
@override @override
Color? get backgroundColor => Theme.of(context).dialogBackgroundColor; Color? get backgroundColor => Theme.of(context).dialogBackgroundColor;
@override
Color? get shadowColor => Theme.of(context).shadowColor;
@override @override
TextStyle? get titleTextStyle => _textTheme.titleLarge; TextStyle? get titleTextStyle => _textTheme.titleLarge;
...@@ -1330,9 +1406,14 @@ class _DialogDefaultsM3 extends DialogTheme { ...@@ -1330,9 +1406,14 @@ class _DialogDefaultsM3 extends DialogTheme {
@override @override
Color? get iconColor => _colors.secondary; Color? get iconColor => _colors.secondary;
// TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160
@override @override
Color? get backgroundColor => ElevationOverlay.colorWithOverlay(_colors.surface, _colors.primary, 6.0); Color? get backgroundColor => _colors.surface;
@override
Color? get shadowColor => Colors.transparent;
@override
Color? get surfaceTintColor => _colors.surfaceTint;
@override @override
TextStyle? get titleTextStyle => _textTheme.headlineSmall; TextStyle? get titleTextStyle => _textTheme.headlineSmall;
......
...@@ -30,6 +30,8 @@ class DialogTheme with Diagnosticable { ...@@ -30,6 +30,8 @@ class DialogTheme with Diagnosticable {
const DialogTheme({ const DialogTheme({
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.shape, this.shape,
this.alignment, this.alignment,
this.iconColor, this.iconColor,
...@@ -44,6 +46,12 @@ class DialogTheme with Diagnosticable { ...@@ -44,6 +46,12 @@ class DialogTheme with Diagnosticable {
/// Overrides the default value for [Dialog.elevation]. /// Overrides the default value for [Dialog.elevation].
final double? elevation; final double? elevation;
/// Overrides the default value for [Dialog.shadowColor].
final Color? shadowColor;
/// Overrides the default value for [Dialog.surfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value for [Dialog.shape]. /// Overrides the default value for [Dialog.shape].
final ShapeBorder? shape; final ShapeBorder? shape;
...@@ -69,6 +77,8 @@ class DialogTheme with Diagnosticable { ...@@ -69,6 +77,8 @@ class DialogTheme with Diagnosticable {
DialogTheme copyWith({ DialogTheme copyWith({
Color? backgroundColor, Color? backgroundColor,
double? elevation, double? elevation,
Color? shadowColor,
Color? surfaceTintColor,
ShapeBorder? shape, ShapeBorder? shape,
AlignmentGeometry? alignment, AlignmentGeometry? alignment,
Color? iconColor, Color? iconColor,
...@@ -79,6 +89,8 @@ class DialogTheme with Diagnosticable { ...@@ -79,6 +89,8 @@ class DialogTheme with Diagnosticable {
return DialogTheme( return DialogTheme(
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
elevation: elevation ?? this.elevation, elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
shape: shape ?? this.shape, shape: shape ?? this.shape,
alignment: alignment ?? this.alignment, alignment: alignment ?? this.alignment,
iconColor: iconColor ?? this.iconColor, iconColor: iconColor ?? this.iconColor,
...@@ -103,6 +115,8 @@ class DialogTheme with Diagnosticable { ...@@ -103,6 +115,8 @@ class DialogTheme with Diagnosticable {
return DialogTheme( return DialogTheme(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
alignment: AlignmentGeometry.lerp(a?.alignment, b?.alignment, t), alignment: AlignmentGeometry.lerp(a?.alignment, b?.alignment, t),
iconColor: Color.lerp(a?.iconColor, b?.iconColor, t), iconColor: Color.lerp(a?.iconColor, b?.iconColor, t),
...@@ -126,6 +140,8 @@ class DialogTheme with Diagnosticable { ...@@ -126,6 +140,8 @@ class DialogTheme with Diagnosticable {
return other is DialogTheme return other is DialogTheme
&& other.backgroundColor == backgroundColor && other.backgroundColor == backgroundColor
&& other.elevation == elevation && other.elevation == elevation
&& other.shadowColor == shadowColor
&& other.surfaceTintColor == surfaceTintColor
&& other.shape == shape && other.shape == shape
&& other.alignment == alignment && other.alignment == alignment
&& other.iconColor == iconColor && other.iconColor == iconColor
...@@ -139,6 +155,8 @@ class DialogTheme with Diagnosticable { ...@@ -139,6 +155,8 @@ class DialogTheme with Diagnosticable {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(ColorProperty('backgroundColor', backgroundColor)); properties.add(ColorProperty('backgroundColor', backgroundColor));
properties.add(DoubleProperty('elevation', elevation)); properties.add(DoubleProperty('elevation', elevation));
properties.add(ColorProperty('shadowColor', shadowColor));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment, defaultValue: null)); properties.add(DiagnosticsProperty<AlignmentGeometry>('alignment', alignment, defaultValue: null));
properties.add(ColorProperty('iconColor', iconColor)); properties.add(ColorProperty('iconColor', iconColor));
......
...@@ -147,6 +147,8 @@ class Drawer extends StatelessWidget { ...@@ -147,6 +147,8 @@ class Drawer extends StatelessWidget {
super.key, super.key,
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.shape, this.shape,
this.width, this.width,
this.child, this.child,
...@@ -168,6 +170,40 @@ class Drawer extends StatelessWidget { ...@@ -168,6 +170,40 @@ class Drawer extends StatelessWidget {
/// is also null, then it defaults to 16.0. /// is also null, then it defaults to 16.0.
final double? elevation; final double? elevation;
/// The color used to paint a drop shadow under the drawer's [Material],
/// which reflects the drawer's [elevation].
///
/// If null and [ThemeData.useMaterial3] is true then no drop shadow will
/// be rendered.
///
/// If null and [ThemeData.useMaterial3] is false then it will default to
/// [ThemeData.shadowColor].
///
/// See also:
/// * [Material.shadowColor], which describes how the drop shadow is painted.
/// * [elevation], which affects how the drop shadow is painted.
/// * [surfaceTintColor], which can be used to indicate elevation through
/// tinting the background color.
final Color? shadowColor;
/// The color used as a surface tint overlay on the drawer's background color,
/// which reflects the drawer's [elevation].
///
/// If [ThemeData.useMaterial3] is false property has no effect.
///
/// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
/// [ColorScheme.surfaceTint] will be used.
///
/// To disable this feature, set [surfaceTintColor] to [Colors.transparent].
///
/// See also:
/// * [Material.surfaceTintColor], which describes how the surface tint will
/// be applied to the background color of the drawer.
/// * [elevation], which affects the opacity of the surface tint.
/// * [shadowColor], which can be used to indicate elevation through
/// a drop shadow.
final Color? surfaceTintColor;
/// The shape of the drawer. /// The shape of the drawer.
/// ///
/// Defines the drawer's [Material.shape]. /// Defines the drawer's [Material.shape].
...@@ -189,7 +225,7 @@ class Drawer extends StatelessWidget { ...@@ -189,7 +225,7 @@ class Drawer extends StatelessWidget {
/// {@macro flutter.widgets.ProxyWidget.child} /// {@macro flutter.widgets.ProxyWidget.child}
final Widget? child; final Widget? child;
/// The semantic label of the dialog used by accessibility frameworks to /// The semantic label of the drawer used by accessibility frameworks to
/// announce screen transitions when the drawer is opened and closed. /// announce screen transitions when the drawer is opened and closed.
/// ///
/// If this label is not provided, it will default to /// If this label is not provided, it will default to
...@@ -216,6 +252,7 @@ class Drawer extends StatelessWidget { ...@@ -216,6 +252,7 @@ class Drawer extends StatelessWidget {
case TargetPlatform.windows: case TargetPlatform.windows:
label = semanticLabel ?? MaterialLocalizations.of(context).drawerLabel; label = semanticLabel ?? MaterialLocalizations.of(context).drawerLabel;
} }
final bool useMaterial3 = Theme.of(context).useMaterial3;
return Semantics( return Semantics(
scopesRoute: true, scopesRoute: true,
namesRoute: true, namesRoute: true,
...@@ -226,6 +263,8 @@ class Drawer extends StatelessWidget { ...@@ -226,6 +263,8 @@ class Drawer extends StatelessWidget {
child: Material( child: Material(
color: backgroundColor ?? drawerTheme.backgroundColor, color: backgroundColor ?? drawerTheme.backgroundColor,
elevation: elevation ?? drawerTheme.elevation ?? 16.0, elevation: elevation ?? drawerTheme.elevation ?? 16.0,
shadowColor: shadowColor ?? drawerTheme.shadowColor ?? (useMaterial3 ? Colors.transparent : Theme.of(context).shadowColor),
surfaceTintColor: surfaceTintColor ?? drawerTheme.surfaceTintColor ?? (useMaterial3 ? Theme.of(context).colorScheme.surfaceTint : null),
shape: shape ?? drawerTheme.shape, shape: shape ?? drawerTheme.shape,
child: child, child: child,
), ),
......
...@@ -38,6 +38,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -38,6 +38,8 @@ class DrawerThemeData with Diagnosticable {
this.backgroundColor, this.backgroundColor,
this.scrimColor, this.scrimColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.shape, this.shape,
this.width, this.width,
}); });
...@@ -51,6 +53,12 @@ class DrawerThemeData with Diagnosticable { ...@@ -51,6 +53,12 @@ class DrawerThemeData with Diagnosticable {
/// Overrides the default value of [Drawer.elevation]. /// Overrides the default value of [Drawer.elevation].
final double? elevation; final double? elevation;
/// Overrides the default value for [Drawer.shadowColor].
final Color? shadowColor;
/// Overrides the default value for [Drawer.surfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value of [Drawer.shape]. /// Overrides the default value of [Drawer.shape].
final ShapeBorder? shape; final ShapeBorder? shape;
...@@ -63,6 +71,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -63,6 +71,8 @@ class DrawerThemeData with Diagnosticable {
Color? backgroundColor, Color? backgroundColor,
Color? scrimColor, Color? scrimColor,
double? elevation, double? elevation,
Color? shadowColor,
Color? surfaceTintColor,
ShapeBorder? shape, ShapeBorder? shape,
double? width, double? width,
}) { }) {
...@@ -70,6 +80,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -70,6 +80,8 @@ class DrawerThemeData with Diagnosticable {
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
scrimColor: scrimColor ?? this.scrimColor, scrimColor: scrimColor ?? this.scrimColor,
elevation: elevation ?? this.elevation, elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
shape: shape ?? this.shape, shape: shape ?? this.shape,
width: width ?? this.width, width: width ?? this.width,
); );
...@@ -89,6 +101,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -89,6 +101,8 @@ class DrawerThemeData with Diagnosticable {
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, t), scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
width: lerpDouble(a?.width, b?.width, t), width: lerpDouble(a?.width, b?.width, t),
); );
...@@ -99,6 +113,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -99,6 +113,8 @@ class DrawerThemeData with Diagnosticable {
backgroundColor, backgroundColor,
scrimColor, scrimColor,
elevation, elevation,
shadowColor,
surfaceTintColor,
shape, shape,
width, width,
); );
...@@ -115,6 +131,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -115,6 +131,8 @@ class DrawerThemeData with Diagnosticable {
&& other.backgroundColor == backgroundColor && other.backgroundColor == backgroundColor
&& other.scrimColor == scrimColor && other.scrimColor == scrimColor
&& other.elevation == elevation && other.elevation == elevation
&& other.shadowColor == shadowColor
&& other.surfaceTintColor == surfaceTintColor
&& other.shape == shape && other.shape == shape
&& other.width == width; && other.width == width;
} }
...@@ -125,6 +143,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -125,6 +143,8 @@ class DrawerThemeData with Diagnosticable {
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null)); properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null)); properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null)); properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DoubleProperty('width', width, defaultValue: null)); properties.add(DoubleProperty('width', width, defaultValue: null));
} }
......
...@@ -582,11 +582,11 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle { ...@@ -582,11 +582,11 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color>? get shadowColor => MaterialStateProperty<Color>? get shadowColor =>
ButtonStyleButton.allOrNull<Color>(_colors.shadow); MaterialStatePropertyAll<Color>(_colors.shadow);
@override @override
MaterialStateProperty<Color>? get surfaceTintColor => MaterialStateProperty<Color>? get surfaceTintColor =>
ButtonStyleButton.allOrNull<Color>(_colors.surfaceTint); MaterialStatePropertyAll<Color>(_colors.surfaceTint);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<double>? get elevation =>
...@@ -608,23 +608,23 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle { ...@@ -608,23 +608,23 @@ class _ElevatedButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -6,6 +6,7 @@ import 'dart:math' as math; ...@@ -6,6 +6,7 @@ import 'dart:math' as math;
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
import 'colors.dart';
import 'theme.dart'; import 'theme.dart';
/// A utility class for dealing with the overlay color needed /// A utility class for dealing with the overlay color needed
...@@ -23,11 +24,12 @@ class ElevationOverlay { ...@@ -23,11 +24,12 @@ class ElevationOverlay {
/// elevated. The amount of opacity will vary with the elevation as described /// elevated. The amount of opacity will vary with the elevation as described
/// in: https://m3.material.io/styles/color/the-color-system/color-roles. /// in: https://m3.material.io/styles/color/the-color-system/color-roles.
/// ///
/// If [surfaceTint] is not null then the returned color will be the given /// If [surfaceTint] is not null and not completely transparent ([Color.alpha]
/// [color] with the [surfaceTint] of the appropriate opacity applies to it. /// is 0), then the returned color will be the given [color] with the
/// Otherwise it will just return [color] unmodified. /// [surfaceTint] of the appropriate opacity applied to it. Otherwise it will
/// just return [color] unmodified.
static Color applySurfaceTint(Color color, Color? surfaceTint, double elevation) { static Color applySurfaceTint(Color color, Color? surfaceTint, double elevation) {
if (surfaceTint != null) { if (surfaceTint != null && surfaceTint != Colors.transparent) {
return Color.alphaBlend(surfaceTint.withOpacity(_surfaceTintOpacityForElevation(elevation)), color); return Color.alphaBlend(surfaceTint.withOpacity(_surfaceTintOpacityForElevation(elevation)), color);
} }
return color; return color;
......
...@@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart'; ...@@ -11,6 +11,7 @@ import 'package:flutter/widgets.dart';
import 'button_style.dart'; import 'button_style.dart';
import 'button_style_button.dart'; import 'button_style_button.dart';
import 'color_scheme.dart'; import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart'; import 'constants.dart';
import 'filled_button_theme.dart'; import 'filled_button_theme.dart';
import 'ink_well.dart'; import 'ink_well.dart';
...@@ -551,9 +552,11 @@ class _FilledButtonDefaultsM3 extends ButtonStyle { ...@@ -551,9 +552,11 @@ class _FilledButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color>? get shadowColor => MaterialStateProperty<Color>? get shadowColor =>
ButtonStyleButton.allOrNull<Color>(_colors.shadow); MaterialStatePropertyAll<Color>(_colors.shadow);
// No default surface tint color @override
MaterialStateProperty<Color>? get surfaceTintColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<double>? get elevation =>
...@@ -575,23 +578,23 @@ class _FilledButtonDefaultsM3 extends ButtonStyle { ...@@ -575,23 +578,23 @@ class _FilledButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
...@@ -673,9 +676,11 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle { ...@@ -673,9 +676,11 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color>? get shadowColor => MaterialStateProperty<Color>? get shadowColor =>
ButtonStyleButton.allOrNull<Color>(_colors.shadow); MaterialStatePropertyAll<Color>(_colors.shadow);
// No default surface tint color @override
MaterialStateProperty<Color>? get surfaceTintColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<double>? get elevation =>
...@@ -697,23 +702,23 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle { ...@@ -697,23 +702,23 @@ class _FilledTonalButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -222,7 +222,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData { ...@@ -222,7 +222,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
Color? get shadowColor => Theme.of(context).colorScheme.shadow; Color? get shadowColor => Theme.of(context).colorScheme.shadow;
@override @override
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint; Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@override @override
Color? get selectedColor => isEnabled Color? get selectedColor => isEnabled
......
...@@ -979,7 +979,7 @@ class _IconButtonDefaultsM3 extends ButtonStyle { ...@@ -979,7 +979,7 @@ class _IconButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color?>? get backgroundColor => MaterialStateProperty<Color?>? get backgroundColor =>
ButtonStyleButton.allOrNull<Color>(Colors.transparent); const MaterialStatePropertyAll<Color?>(Colors.transparent);
@override @override
MaterialStateProperty<Color?>? get foregroundColor => MaterialStateProperty<Color?>? get foregroundColor =>
...@@ -1019,37 +1019,41 @@ class _IconButtonDefaultsM3 extends ButtonStyle { ...@@ -1019,37 +1019,41 @@ class _IconButtonDefaultsM3 extends ButtonStyle {
return null; return null;
}); });
// No default shadow color @override
MaterialStateProperty<double>? get elevation =>
const MaterialStatePropertyAll<double>(0.0);
// No default surface tint color @override
MaterialStateProperty<Color>? get shadowColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<Color>? get surfaceTintColor =>
ButtonStyleButton.allOrNull<double>(0.0); const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0)); const MaterialStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.all(8.0));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(40.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(40.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
@override @override
MaterialStateProperty<double>? get iconSize => MaterialStateProperty<double>? get iconSize =>
ButtonStyleButton.allOrNull<double>(24.0); const MaterialStatePropertyAll<double>(24.0);
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart'; ...@@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';
import 'chip.dart'; import 'chip.dart';
import 'chip_theme.dart'; import 'chip_theme.dart';
import 'colors.dart';
import 'debug.dart'; import 'debug.dart';
import 'icons.dart'; import 'icons.dart';
import 'theme.dart'; import 'theme.dart';
...@@ -268,10 +269,10 @@ class _InputChipDefaultsM3 extends ChipThemeData { ...@@ -268,10 +269,10 @@ class _InputChipDefaultsM3 extends ChipThemeData {
Color? get backgroundColor => null; Color? get backgroundColor => null;
@override @override
Color? get shadowColor => null; Color? get shadowColor => Colors.transparent;
@override @override
@override Color? get surfaceTintColor => null; Color? get surfaceTintColor => Colors.transparent;
@override @override
Color? get selectedColor => Theme.of(context).colorScheme.secondaryContainer; Color? get selectedColor => Theme.of(context).colorScheme.secondaryContainer;
......
...@@ -258,12 +258,12 @@ class Material extends StatefulWidget { ...@@ -258,12 +258,12 @@ class Material extends StatefulWidget {
/// The color to paint the shadow below the material. /// The color to paint the shadow below the material.
/// ///
/// When [ThemeData.useMaterial3] is true, and this is null, then no drop /// If null and [ThemeData.useMaterial3] is true then [ThemeData]'s
/// shadow will be rendered for this material. If it is non-null, then this /// [ColorScheme.shadow] will be used. If [ThemeData.useMaterial3] is false
/// color will be used to render a drop shadow below the material. /// then [ThemeData.shadowColor] will be used.
/// ///
/// When [ThemeData.useMaterial3] is false, and this is null, then /// To remove the drop shadow when [elevation] is greater than 0, set
/// [ThemeData.shadowColor] is used, which defaults to fully opaque black. /// [shadowColor] to [Colors.transparent].
/// ///
/// See also: /// See also:
/// * [ThemeData.useMaterial3], which determines the default value for this /// * [ThemeData.useMaterial3], which determines the default value for this
...@@ -282,9 +282,9 @@ class Material extends StatefulWidget { ...@@ -282,9 +282,9 @@ class Material extends StatefulWidget {
/// ///
/// If [ThemeData.useMaterial3] is false, then this property is not used. /// If [ThemeData.useMaterial3] is false, then this property is not used.
/// ///
/// If [ThemeData.useMaterial3] is true and [surfaceTintColor] is not null, /// If [ThemeData.useMaterial3] is true and [surfaceTintColor] is not null and
/// then it will be used to overlay the base [color] with an opacity based /// not [Colors.transparent], then it will be used to overlay the base [color]
/// on the [elevation]. /// with an opacity based on the [elevation].
/// ///
/// Otherwise, no surface tint will be applied. /// Otherwise, no surface tint will be applied.
/// ///
...@@ -404,7 +404,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -404,7 +404,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final Color? backgroundColor = _getBackgroundColor(context); final Color? backgroundColor = _getBackgroundColor(context);
final Color? modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? null : theme.shadowColor); final Color modelShadowColor = widget.shadowColor ?? (theme.useMaterial3 ? theme.colorScheme.shadow : theme.shadowColor);
// If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted. // If no shadow color is specified, use 0 for elevation in the model so a drop shadow won't be painted.
final double modelElevation = modelShadowColor != null ? widget.elevation : 0; final double modelElevation = modelShadowColor != null ? widget.elevation : 0;
assert( assert(
...@@ -458,7 +458,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin { ...@@ -458,7 +458,7 @@ class _MaterialState extends State<Material> with TickerProviderStateMixin {
clipBehavior: widget.clipBehavior, clipBehavior: widget.clipBehavior,
elevation: modelElevation, elevation: modelElevation,
color: color, color: color,
shadowColor: modelShadowColor ?? const Color(0x00000000), shadowColor: modelShadowColor,
animateColor: false, animateColor: false,
child: contents, child: contents,
); );
......
...@@ -67,8 +67,9 @@ class NavigationBar extends StatelessWidget { ...@@ -67,8 +67,9 @@ class NavigationBar extends StatelessWidget {
required this.destinations, required this.destinations,
this.onDestinationSelected, this.onDestinationSelected,
this.backgroundColor, this.backgroundColor,
this.surfaceTintColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.height, this.height,
this.labelBehavior, this.labelBehavior,
}) : assert(destinations != null && destinations.length >= 2), }) : assert(destinations != null && destinations.length >= 2),
...@@ -109,6 +110,22 @@ class NavigationBar extends StatelessWidget { ...@@ -109,6 +110,22 @@ class NavigationBar extends StatelessWidget {
/// and [ColorScheme.onSurface] using an [ElevationOverlay]. /// and [ColorScheme.onSurface] using an [ElevationOverlay].
final Color? backgroundColor; final Color? backgroundColor;
/// The elevation of the [NavigationBar] itself.
///
/// If null, [NavigationBarThemeData.elevation] is used. If that
/// is also null, then if [ThemeData.useMaterial3] is true then it will
/// be 3.0 otherwise 0.0.
final double? elevation;
/// The color used for the drop shadow to indicate elevation.
///
/// If null, [NavigationBarThemeData.shadowColor] is used. If that
/// is also null, the default value is [Colors.transparent] which
/// indicates that no drop shadow will be displayed.
///
/// See [Material.shadowColor] for more details on drop shadows.
final Color? shadowColor;
/// The color used as an overlay on [backgroundColor] to indicate elevation. /// The color used as an overlay on [backgroundColor] to indicate elevation.
/// ///
/// If null, [NavigationBarThemeData.surfaceTintColor] is used. If that /// If null, [NavigationBarThemeData.surfaceTintColor] is used. If that
...@@ -118,13 +135,6 @@ class NavigationBar extends StatelessWidget { ...@@ -118,13 +135,6 @@ class NavigationBar extends StatelessWidget {
/// overlay is applied. /// overlay is applied.
final Color? surfaceTintColor; final Color? surfaceTintColor;
/// The elevation of the [NavigationBar] itself.
///
/// If null, [NavigationBarThemeData.elevation] is used. If that
/// is also null, then if [ThemeData.useMaterial3] is true then it will
/// be 3.0 otherwise 0.0.
final double? elevation;
/// The height of the [NavigationBar] itself. /// The height of the [NavigationBar] itself.
/// ///
/// If this is used in [Scaffold.bottomNavigationBar] and the scaffold is /// If this is used in [Scaffold.bottomNavigationBar] and the scaffold is
...@@ -171,8 +181,9 @@ class NavigationBar extends StatelessWidget { ...@@ -171,8 +181,9 @@ class NavigationBar extends StatelessWidget {
color: backgroundColor color: backgroundColor
?? navigationBarTheme.backgroundColor ?? navigationBarTheme.backgroundColor
?? defaults.backgroundColor!, ?? defaults.backgroundColor!,
surfaceTintColor: surfaceTintColor ?? navigationBarTheme.surfaceTintColor ?? defaults.surfaceTintColor,
elevation: elevation ?? navigationBarTheme.elevation ?? defaults.elevation!, elevation: elevation ?? navigationBarTheme.elevation ?? defaults.elevation!,
shadowColor: shadowColor ?? navigationBarTheme.shadowColor ?? defaults.shadowColor,
surfaceTintColor: surfaceTintColor ?? navigationBarTheme.surfaceTintColor ?? defaults.surfaceTintColor,
child: SafeArea( child: SafeArea(
child: SizedBox( child: SizedBox(
height: effectiveHeight, height: effectiveHeight,
...@@ -1250,6 +1261,8 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData { ...@@ -1250,6 +1261,8 @@ class _NavigationBarDefaultsM3 extends NavigationBarThemeData {
@override Color? get backgroundColor => _colors.surface; @override Color? get backgroundColor => _colors.surface;
@override Color? get shadowColor => Colors.transparent;
@override Color? get surfaceTintColor => _colors.surfaceTint; @override Color? get surfaceTintColor => _colors.surfaceTint;
@override MaterialStateProperty<IconThemeData?>? get iconTheme { @override MaterialStateProperty<IconThemeData?>? get iconTheme {
......
...@@ -44,8 +44,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -44,8 +44,9 @@ class NavigationBarThemeData with Diagnosticable {
const NavigationBarThemeData({ const NavigationBarThemeData({
this.height, this.height,
this.backgroundColor, this.backgroundColor,
this.surfaceTintColor,
this.elevation, this.elevation,
this.shadowColor,
this.surfaceTintColor,
this.indicatorColor, this.indicatorColor,
this.indicatorShape, this.indicatorShape,
this.labelTextStyle, this.labelTextStyle,
...@@ -59,12 +60,15 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -59,12 +60,15 @@ class NavigationBarThemeData with Diagnosticable {
/// Overrides the default value of [NavigationBar.backgroundColor]. /// Overrides the default value of [NavigationBar.backgroundColor].
final Color? backgroundColor; final Color? backgroundColor;
/// Overrides the default value of [NavigationBar.surfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value of [NavigationBar.elevation]. /// Overrides the default value of [NavigationBar.elevation].
final double? elevation; final double? elevation;
/// Overrides the default value of [NavigationBar.shadowColor].
final Color? shadowColor;
/// Overrides the default value of [NavigationBar.surfaceTintColor].
final Color? surfaceTintColor;
/// Overrides the default value of [NavigationBar]'s selection indicator. /// Overrides the default value of [NavigationBar]'s selection indicator.
final Color? indicatorColor; final Color? indicatorColor;
...@@ -92,8 +96,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -92,8 +96,9 @@ class NavigationBarThemeData with Diagnosticable {
NavigationBarThemeData copyWith({ NavigationBarThemeData copyWith({
double? height, double? height,
Color? backgroundColor, Color? backgroundColor,
Color? surfaceTintColor,
double? elevation, double? elevation,
Color? shadowColor,
Color? surfaceTintColor,
Color? indicatorColor, Color? indicatorColor,
ShapeBorder? indicatorShape, ShapeBorder? indicatorShape,
MaterialStateProperty<TextStyle?>? labelTextStyle, MaterialStateProperty<TextStyle?>? labelTextStyle,
...@@ -103,8 +108,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -103,8 +108,9 @@ class NavigationBarThemeData with Diagnosticable {
return NavigationBarThemeData( return NavigationBarThemeData(
height: height ?? this.height, height: height ?? this.height,
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
elevation: elevation ?? this.elevation, elevation: elevation ?? this.elevation,
shadowColor: shadowColor ?? this.shadowColor,
surfaceTintColor: surfaceTintColor ?? this.surfaceTintColor,
indicatorColor: indicatorColor ?? this.indicatorColor, indicatorColor: indicatorColor ?? this.indicatorColor,
indicatorShape: indicatorShape ?? this.indicatorShape, indicatorShape: indicatorShape ?? this.indicatorShape,
labelTextStyle: labelTextStyle ?? this.labelTextStyle, labelTextStyle: labelTextStyle ?? this.labelTextStyle,
...@@ -126,8 +132,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -126,8 +132,9 @@ class NavigationBarThemeData with Diagnosticable {
return NavigationBarThemeData( return NavigationBarThemeData(
height: lerpDouble(a?.height, b?.height, t), height: lerpDouble(a?.height, b?.height, t),
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
shadowColor: Color.lerp(a?.shadowColor, b?.shadowColor, t),
surfaceTintColor: Color.lerp(a?.surfaceTintColor, b?.surfaceTintColor, t),
indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t), indicatorColor: Color.lerp(a?.indicatorColor, b?.indicatorColor, t),
indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t), indicatorShape: ShapeBorder.lerp(a?.indicatorShape, b?.indicatorShape, t),
labelTextStyle: MaterialStateProperty.lerp<TextStyle?>(a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp), labelTextStyle: MaterialStateProperty.lerp<TextStyle?>(a?.labelTextStyle, b?.labelTextStyle, t, TextStyle.lerp),
...@@ -140,8 +147,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -140,8 +147,9 @@ class NavigationBarThemeData with Diagnosticable {
int get hashCode => Object.hash( int get hashCode => Object.hash(
height, height,
backgroundColor, backgroundColor,
surfaceTintColor,
elevation, elevation,
shadowColor,
surfaceTintColor,
indicatorColor, indicatorColor,
indicatorShape, indicatorShape,
labelTextStyle, labelTextStyle,
...@@ -160,8 +168,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -160,8 +168,9 @@ class NavigationBarThemeData with Diagnosticable {
return other is NavigationBarThemeData return other is NavigationBarThemeData
&& other.height == height && other.height == height
&& other.backgroundColor == backgroundColor && other.backgroundColor == backgroundColor
&& other.surfaceTintColor == surfaceTintColor
&& other.elevation == elevation && other.elevation == elevation
&& other.shadowColor == shadowColor
&& other.surfaceTintColor == surfaceTintColor
&& other.indicatorColor == indicatorColor && other.indicatorColor == indicatorColor
&& other.indicatorShape == indicatorShape && other.indicatorShape == indicatorShape
&& other.labelTextStyle == labelTextStyle && other.labelTextStyle == labelTextStyle
...@@ -174,8 +183,9 @@ class NavigationBarThemeData with Diagnosticable { ...@@ -174,8 +183,9 @@ class NavigationBarThemeData with Diagnosticable {
super.debugFillProperties(properties); super.debugFillProperties(properties);
properties.add(DoubleProperty('height', height, defaultValue: null)); properties.add(DoubleProperty('height', height, defaultValue: null));
properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null)); properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null)); properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(ColorProperty('shadowColor', shadowColor, defaultValue: null));
properties.add(ColorProperty('surfaceTintColor', surfaceTintColor, defaultValue: null));
properties.add(ColorProperty('indicatorColor', indicatorColor, defaultValue: null)); properties.add(ColorProperty('indicatorColor', indicatorColor, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('indicatorShape', indicatorShape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('indicatorShape', indicatorShape, defaultValue: null));
properties.add(DiagnosticsProperty<MaterialStateProperty<TextStyle?>>('labelTextStyle', labelTextStyle, defaultValue: null)); properties.add(DiagnosticsProperty<MaterialStateProperty<TextStyle?>>('labelTextStyle', labelTextStyle, defaultValue: null));
......
...@@ -470,7 +470,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle { ...@@ -470,7 +470,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color?>? get backgroundColor => MaterialStateProperty<Color?>? get backgroundColor =>
ButtonStyleButton.allOrNull<Color>(Colors.transparent); const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<Color?>? get foregroundColor => MaterialStateProperty<Color?>? get foregroundColor =>
...@@ -496,27 +496,31 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle { ...@@ -496,27 +496,31 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
return null; return null;
}); });
// No default shadow color @override
MaterialStateProperty<Color>? get shadowColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
// No default surface tint color @override
MaterialStateProperty<Color>? get surfaceTintColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<double>? get elevation =>
ButtonStyleButton.allOrNull<double>(0.0); const MaterialStatePropertyAll<double>(0.0);
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
@override @override
MaterialStateProperty<BorderSide>? get side => MaterialStateProperty<BorderSide>? get side =>
...@@ -529,7 +533,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle { ...@@ -529,7 +533,7 @@ class _OutlinedButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -514,7 +514,7 @@ class _TextButtonDefaultsM3 extends ButtonStyle { ...@@ -514,7 +514,7 @@ class _TextButtonDefaultsM3 extends ButtonStyle {
@override @override
MaterialStateProperty<Color?>? get backgroundColor => MaterialStateProperty<Color?>? get backgroundColor =>
ButtonStyleButton.allOrNull<Color>(Colors.transparent); const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<Color?>? get foregroundColor => MaterialStateProperty<Color?>? get foregroundColor =>
...@@ -540,33 +540,37 @@ class _TextButtonDefaultsM3 extends ButtonStyle { ...@@ -540,33 +540,37 @@ class _TextButtonDefaultsM3 extends ButtonStyle {
return null; return null;
}); });
// No default shadow color @override
MaterialStateProperty<Color>? get shadowColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
// No default surface tint color @override
MaterialStateProperty<Color>? get surfaceTintColor =>
const MaterialStatePropertyAll<Color>(Colors.transparent);
@override @override
MaterialStateProperty<double>? get elevation => MaterialStateProperty<double>? get elevation =>
ButtonStyleButton.allOrNull<double>(0.0); const MaterialStatePropertyAll<double>(0.0);
@override @override
MaterialStateProperty<EdgeInsetsGeometry>? get padding => MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context)); MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override @override
MaterialStateProperty<Size>? get minimumSize => MaterialStateProperty<Size>? get minimumSize =>
ButtonStyleButton.allOrNull<Size>(const Size(64.0, 40.0)); const MaterialStatePropertyAll<Size>(Size(64.0, 40.0));
// No default fixedSize // No default fixedSize
@override @override
MaterialStateProperty<Size>? get maximumSize => MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite); const MaterialStatePropertyAll<Size>(Size.infinite);
// No default side // No default side
@override @override
MaterialStateProperty<OutlinedBorder>? get shape => MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(const StadiumBorder()); const MaterialStatePropertyAll<OutlinedBorder>(StadiumBorder());
@override @override
MaterialStateProperty<MouseCursor?>? get mouseCursor => MaterialStateProperty<MouseCursor?>? get mouseCursor =>
......
...@@ -140,9 +140,13 @@ void main() { ...@@ -140,9 +140,13 @@ void main() {
testWidgets('Custom dialog elevation', (WidgetTester tester) async { testWidgets('Custom dialog elevation', (WidgetTester tester) async {
const double customElevation = 12.0; const double customElevation = 12.0;
const Color shadowColor = Color(0xFF000001);
const Color surfaceTintColor = Color(0xFF000002);
const AlertDialog dialog = AlertDialog( const AlertDialog dialog = AlertDialog(
actions: <Widget>[ ], actions: <Widget>[ ],
elevation: customElevation, elevation: customElevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
); );
await tester.pumpWidget(_buildAppWithDialog(dialog)); await tester.pumpWidget(_buildAppWithDialog(dialog));
...@@ -151,6 +155,8 @@ void main() { ...@@ -151,6 +155,8 @@ void main() {
final Material materialWidget = _getMaterialFromDialog(tester); final Material materialWidget = _getMaterialFromDialog(tester);
expect(materialWidget.elevation, customElevation); expect(materialWidget.elevation, customElevation);
expect(materialWidget.shadowColor, shadowColor);
expect(materialWidget.surfaceTintColor, surfaceTintColor);
}); });
testWidgets('Custom Title Text Style', (WidgetTester tester) async { testWidgets('Custom Title Text Style', (WidgetTester tester) async {
......
...@@ -51,6 +51,8 @@ void main() { ...@@ -51,6 +51,8 @@ void main() {
const DialogTheme( const DialogTheme(
backgroundColor: Color(0xff123456), backgroundColor: Color(0xff123456),
elevation: 8.0, elevation: 8.0,
shadowColor: Color(0xff000001),
surfaceTintColor: Color(0xff000002),
alignment: Alignment.bottomLeft, alignment: Alignment.bottomLeft,
iconColor: Color(0xff654321), iconColor: Color(0xff654321),
titleTextStyle: TextStyle(color: Color(0xffffffff)), titleTextStyle: TextStyle(color: Color(0xffffffff)),
...@@ -63,6 +65,8 @@ void main() { ...@@ -63,6 +65,8 @@ void main() {
expect(description, <String>[ expect(description, <String>[
'backgroundColor: Color(0xff123456)', 'backgroundColor: Color(0xff123456)',
'elevation: 8.0', 'elevation: 8.0',
'shadowColor: Color(0xff000001)',
'surfaceTintColor: Color(0xff000002)',
'alignment: Alignment.bottomLeft', 'alignment: Alignment.bottomLeft',
'iconColor: Color(0xff654321)', 'iconColor: Color(0xff654321)',
'titleTextStyle: TextStyle(inherit: true, color: Color(0xffffffff))', 'titleTextStyle: TextStyle(inherit: true, color: Color(0xffffffff))',
...@@ -89,11 +93,19 @@ void main() { ...@@ -89,11 +93,19 @@ void main() {
testWidgets('Custom dialog elevation', (WidgetTester tester) async { testWidgets('Custom dialog elevation', (WidgetTester tester) async {
const double customElevation = 12.0; const double customElevation = 12.0;
const Color shadowColor = Color(0xFF000001);
const Color surfaceTintColor = Color(0xFF000002);
const AlertDialog dialog = AlertDialog( const AlertDialog dialog = AlertDialog(
title: Text('Title'), title: Text('Title'),
actions: <Widget>[ ], actions: <Widget>[ ],
); );
final ThemeData theme = ThemeData(dialogTheme: const DialogTheme(elevation: customElevation)); final ThemeData theme = ThemeData(
dialogTheme: const DialogTheme(
elevation: customElevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
),
);
await tester.pumpWidget( await tester.pumpWidget(
_appWithDialog(tester, dialog, theme: theme), _appWithDialog(tester, dialog, theme: theme),
...@@ -103,6 +115,8 @@ void main() { ...@@ -103,6 +115,8 @@ void main() {
final Material materialWidget = _getMaterialFromDialog(tester); final Material materialWidget = _getMaterialFromDialog(tester);
expect(materialWidget.elevation, customElevation); expect(materialWidget.elevation, customElevation);
expect(materialWidget.shadowColor, shadowColor);
expect(materialWidget.surfaceTintColor, surfaceTintColor);
}); });
testWidgets('Custom dialog shape', (WidgetTester tester) async { testWidgets('Custom dialog shape', (WidgetTester tester) async {
......
...@@ -30,6 +30,8 @@ void main() { ...@@ -30,6 +30,8 @@ void main() {
backgroundColor: Color(0x00000099), backgroundColor: Color(0x00000099),
scrimColor: Color(0x00000098), scrimColor: Color(0x00000098),
elevation: 5.0, elevation: 5.0,
shadowColor: Color(0x00000097),
surfaceTintColor: Color(0x00000096),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
width: 200.0, width: 200.0,
).debugFillProperties(builder); ).debugFillProperties(builder);
...@@ -43,6 +45,8 @@ void main() { ...@@ -43,6 +45,8 @@ void main() {
'backgroundColor: Color(0x00000099)', 'backgroundColor: Color(0x00000099)',
'scrimColor: Color(0x00000098)', 'scrimColor: Color(0x00000098)',
'elevation: 5.0', 'elevation: 5.0',
'shadowColor: Color(0x00000097)',
'surfaceTintColor: Color(0x00000096)',
'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))', 'shape: RoundedRectangleBorder(BorderSide(width: 0.0, style: none), BorderRadius.circular(2.0))',
'width: 200.0', 'width: 200.0',
]); ]);
...@@ -50,6 +54,7 @@ void main() { ...@@ -50,6 +54,7 @@ void main() {
testWidgets('Default values are used when no Drawer or DrawerThemeData properties are specified', (WidgetTester tester) async { testWidgets('Default values are used when no Drawer or DrawerThemeData properties are specified', (WidgetTester tester) async {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
final bool useMaterial3 = ThemeData().useMaterial3;
await tester.pumpWidget( await tester.pumpWidget(
MaterialApp( MaterialApp(
home: Scaffold( home: Scaffold(
...@@ -63,6 +68,8 @@ void main() { ...@@ -63,6 +68,8 @@ void main() {
expect(_drawerMaterial(tester).color, null); expect(_drawerMaterial(tester).color, null);
expect(_drawerMaterial(tester).elevation, 16.0); expect(_drawerMaterial(tester).elevation, 16.0);
expect(_drawerMaterial(tester).shadowColor, useMaterial3 ? Colors.transparent : ThemeData().shadowColor);
expect(_drawerMaterial(tester).surfaceTintColor, useMaterial3 ? ThemeData().colorScheme.surfaceTint : null);
expect(_drawerMaterial(tester).shape, null); expect(_drawerMaterial(tester).shape, null);
expect(_scrim(tester).color, Colors.black54); expect(_scrim(tester).color, Colors.black54);
expect(_drawerRenderBox(tester).size.width, 304.0); expect(_drawerRenderBox(tester).size.width, 304.0);
...@@ -72,6 +79,8 @@ void main() { ...@@ -72,6 +79,8 @@ void main() {
const Color backgroundColor = Color(0x00000001); const Color backgroundColor = Color(0x00000001);
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const Color shadowColor = Color(0x00000003);
const Color surfaceTintColor = Color(0x00000004);
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0; const double width = 200.0;
...@@ -83,6 +92,8 @@ void main() { ...@@ -83,6 +92,8 @@ void main() {
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
scrimColor: scrimColor, scrimColor: scrimColor,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
shape: shape, shape: shape,
width: width, width: width,
), ),
...@@ -98,6 +109,8 @@ void main() { ...@@ -98,6 +109,8 @@ void main() {
expect(_drawerMaterial(tester).color, backgroundColor); expect(_drawerMaterial(tester).color, backgroundColor);
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shadowColor, shadowColor);
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width); expect(_drawerRenderBox(tester).size.width, width);
...@@ -107,6 +120,8 @@ void main() { ...@@ -107,6 +120,8 @@ void main() {
const Color backgroundColor = Color(0x00000001); const Color backgroundColor = Color(0x00000001);
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const Color shadowColor = Color(0x00000003);
const Color surfaceTintColor = Color(0x00000004);
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0; const double width = 200.0;
...@@ -115,8 +130,8 @@ void main() { ...@@ -115,8 +130,8 @@ void main() {
MaterialApp( MaterialApp(
theme: ThemeData( theme: ThemeData(
drawerTheme: const DrawerThemeData( drawerTheme: const DrawerThemeData(
backgroundColor: Color(0x00000003), backgroundColor: Color(0x00000005),
scrimColor: Color(0x00000004), scrimColor: Color(0x00000006),
elevation: 13.0, elevation: 13.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0, width: 400.0,
...@@ -128,6 +143,8 @@ void main() { ...@@ -128,6 +143,8 @@ void main() {
drawer: const Drawer( drawer: const Drawer(
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
shape: shape, shape: shape,
width: width, width: width,
), ),
...@@ -139,6 +156,8 @@ void main() { ...@@ -139,6 +156,8 @@ void main() {
expect(_drawerMaterial(tester).color, backgroundColor); expect(_drawerMaterial(tester).color, backgroundColor);
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shadowColor, shadowColor);
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width); expect(_drawerRenderBox(tester).size.width, width);
...@@ -148,6 +167,8 @@ void main() { ...@@ -148,6 +167,8 @@ void main() {
const Color backgroundColor = Color(0x00000001); const Color backgroundColor = Color(0x00000001);
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const Color shadowColor = Color(0x00000003);
const Color surfaceTintColor = Color(0x00000004);
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0; const double width = 200.0;
...@@ -156,9 +177,11 @@ void main() { ...@@ -156,9 +177,11 @@ void main() {
MaterialApp( MaterialApp(
theme: ThemeData( theme: ThemeData(
drawerTheme: const DrawerThemeData( drawerTheme: const DrawerThemeData(
backgroundColor: Color(0x00000003), backgroundColor: Color(0x00000005),
scrimColor: Color(0x00000004), scrimColor: Color(0x00000006),
elevation: 13.0, elevation: 13.0,
shadowColor: Color(0x00000007),
surfaceTintColor: Color(0x00000007),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0 width: 400.0
), ),
...@@ -168,6 +191,8 @@ void main() { ...@@ -168,6 +191,8 @@ void main() {
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
scrimColor: scrimColor, scrimColor: scrimColor,
elevation: elevation, elevation: elevation,
shadowColor: shadowColor,
surfaceTintColor: surfaceTintColor,
shape: shape, shape: shape,
width: width, width: width,
), ),
...@@ -183,6 +208,8 @@ void main() { ...@@ -183,6 +208,8 @@ void main() {
expect(_drawerMaterial(tester).color, backgroundColor); expect(_drawerMaterial(tester).color, backgroundColor);
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shadowColor, shadowColor);
expect(_drawerMaterial(tester).surfaceTintColor, surfaceTintColor);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width); expect(_drawerRenderBox(tester).size.width, width);
......
...@@ -1078,7 +1078,7 @@ void main() { ...@@ -1078,7 +1078,7 @@ void main() {
expect(material.clipBehavior, Clip.none); expect(material.clipBehavior, Clip.none);
expect(material.color, Colors.transparent); expect(material.color, Colors.transparent);
expect(material.elevation, 0.0); expect(material.elevation, 0.0);
expect(material.shadowColor, null); expect(material.shadowColor, Colors.transparent);
expect(material.shape, const StadiumBorder()); expect(material.shape, const StadiumBorder());
expect(material.textStyle, null); expect(material.textStyle, null);
expect(material.type, MaterialType.button); expect(material.type, MaterialType.button);
...@@ -1102,7 +1102,7 @@ void main() { ...@@ -1102,7 +1102,7 @@ void main() {
expect(material.clipBehavior, Clip.none); expect(material.clipBehavior, Clip.none);
expect(material.color, Colors.transparent); expect(material.color, Colors.transparent);
expect(material.elevation, 0.0); expect(material.elevation, 0.0);
expect(material.shadowColor, null); expect(material.shadowColor, Colors.transparent);
expect(material.shape, const StadiumBorder()); expect(material.shape, const StadiumBorder());
expect(material.textStyle, null); expect(material.textStyle, null);
expect(material.type, MaterialType.button); expect(material.type, MaterialType.button);
...@@ -1127,7 +1127,7 @@ void main() { ...@@ -1127,7 +1127,7 @@ void main() {
expect(material.clipBehavior, Clip.none); expect(material.clipBehavior, Clip.none);
expect(material.color, Colors.transparent); expect(material.color, Colors.transparent);
expect(material.elevation, 0.0); expect(material.elevation, 0.0);
expect(material.shadowColor, null); expect(material.shadowColor, Colors.transparent);
expect(material.shape, const StadiumBorder()); expect(material.shape, const StadiumBorder());
expect(material.textStyle, null); expect(material.textStyle, null);
expect(material.type, MaterialType.button); expect(material.type, MaterialType.button);
......
...@@ -32,7 +32,7 @@ void main() { ...@@ -32,7 +32,7 @@ void main() {
expect(material.borderRadius, null); expect(material.borderRadius, null);
expect(material.color, Colors.transparent); expect(material.color, Colors.transparent);
expect(material.elevation, 0.0); expect(material.elevation, 0.0);
expect(material.shadowColor, null); expect(material.shadowColor, Colors.transparent);
expect(material.shape, const StadiumBorder()); expect(material.shape, const StadiumBorder());
expect(material.textStyle, null); expect(material.textStyle, null);
expect(material.type, MaterialType.button); expect(material.type, MaterialType.button);
...@@ -221,12 +221,12 @@ void main() { ...@@ -221,12 +221,12 @@ void main() {
await tester.pumpWidget(buildFrame()); await tester.pumpWidget(buildFrame());
Material material = tester.widget<Material>(buttonMaterialFinder); Material material = tester.widget<Material>(buttonMaterialFinder);
expect(material.shadowColor, null); //default expect(material.shadowColor, Colors.transparent); //default
await tester.pumpWidget(buildFrame(overallShadowColor: shadowColor)); await tester.pumpWidget(buildFrame(overallShadowColor: shadowColor));
await tester.pumpAndSettle(); // theme animation await tester.pumpAndSettle(); // theme animation
material = tester.widget<Material>(buttonMaterialFinder); material = tester.widget<Material>(buttonMaterialFinder);
expect(material.shadowColor, null); expect(material.shadowColor, Colors.transparent);
await tester.pumpWidget(buildFrame(themeShadowColor: shadowColor)); await tester.pumpWidget(buildFrame(themeShadowColor: shadowColor));
await tester.pumpAndSettle(); // theme animation await tester.pumpAndSettle(); // theme animation
......
...@@ -189,6 +189,58 @@ void main() { ...@@ -189,6 +189,58 @@ void main() {
expect(log, isEmpty); expect(log, isEmpty);
}); });
testWidgets('Shadow color defaults', (WidgetTester tester) async {
Widget buildWithShadow(Color? shadowColor) {
return Center(
child: SizedBox(
height: 100.0,
width: 100.0,
child: Material(
shadowColor: shadowColor,
elevation: 10,
shape: const CircleBorder(),
),
)
);
}
// Default M2 shadow color
await tester.pumpWidget(
Theme(
data: ThemeData(
useMaterial3: false,
),
child: buildWithShadow(null),
)
);
await tester.pumpAndSettle();
expect(getModel(tester).shadowColor, ThemeData().shadowColor);
// Default M3 shadow color
await tester.pumpWidget(
Theme(
data: ThemeData(
useMaterial3: true,
),
child: buildWithShadow(null),
)
);
await tester.pumpAndSettle();
expect(getModel(tester).shadowColor, ThemeData().colorScheme.shadow);
// Drop shadow can be turned off with a transparent color.
await tester.pumpWidget(
Theme(
data: ThemeData(
useMaterial3: true,
),
child: buildWithShadow(Colors.transparent),
)
);
await tester.pumpAndSettle();
expect(getModel(tester).shadowColor, Colors.transparent);
});
testWidgets('Shadows animate smoothly', (WidgetTester tester) async { testWidgets('Shadows animate smoothly', (WidgetTester tester) async {
// This code verifies that the PhysicalModel's elevation animates over // This code verifies that the PhysicalModel's elevation animates over
// a kThemeChangeDuration time interval. // a kThemeChangeDuration time interval.
...@@ -304,6 +356,23 @@ void main() { ...@@ -304,6 +356,23 @@ void main() {
final RenderPhysicalShape noTintModel = getModel(tester); final RenderPhysicalShape noTintModel = getModel(tester);
expect(noTintModel.color, equals(baseColor)); expect(noTintModel.color, equals(baseColor));
// With transparent surfaceTintColor, it should not apply an overlay
await tester.pumpWidget(
Theme(
data: ThemeData(
useMaterial3: true,
),
child: buildMaterial(
color: baseColor,
surfaceTintColor: Colors.transparent,
elevation: 12.0,
),
),
);
await tester.pumpAndSettle();
final RenderPhysicalShape transparentTintModel = getModel(tester);
expect(transparentTintModel.color, equals(baseColor));
// With surfaceTintColor specified, it should not apply an overlay based // With surfaceTintColor specified, it should not apply an overlay based
// on the elevation. // on the elevation.
await tester.pumpWidget( await tester.pumpWidget(
......
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