Skip to content

Commit

Permalink
Fixing elevation issues with Material 3 (#110624)
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
darrenaustin committed Sep 6, 2022
1 parent 1b4b480 commit 33ed6a3
Show file tree
Hide file tree
Showing 35 changed files with 506 additions and 145 deletions.
4 changes: 2 additions & 2 deletions dev/tools/gen_defaults/lib/action_chip_template.dart
Expand Up @@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
Expand Down
5 changes: 4 additions & 1 deletion dev/tools/gen_defaults/lib/app_bar_template.dart
Expand Up @@ -34,7 +34,10 @@ class _${blockName}DefaultsM3 extends AppBarTheme {
Color? get foregroundColor => ${color('md.comp.top-app-bar.small.headline.color')};
@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
IconThemeData? get iconTheme => IconThemeData(
Expand Down
28 changes: 16 additions & 12 deletions dev/tools/gen_defaults/lib/button_template.dart
Expand Up @@ -24,7 +24,7 @@ class ButtonTemplate extends TokenTemplate {
}
return '''
ButtonStyleButton.allOrNull<Color>(Colors.transparent)''';
const MaterialStatePropertyAll<Color>(Colors.transparent)''';
}

String _elevation() {
Expand All @@ -49,7 +49,15 @@ class ButtonTemplate extends TokenTemplate {
}
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
Expand Down Expand Up @@ -96,34 +104,30 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
return null;
});
${tokens.containsKey("$tokenGroup.container.shadow-color") ? '''
@override
MaterialStateProperty<Color>? get shadowColor =>
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.shadow-color")});''' : '''
// No default shadow color'''}
${_elevationColor("$tokenGroup.container.shadow-color")};
${tokens.containsKey("$tokenGroup.container.surface-tint-layer.color") ? '''
@override
MaterialStateProperty<Color>? get surfaceTintColor =>
ButtonStyleButton.allOrNull<Color>(${color("$tokenGroup.container.surface-tint-layer.color")});''' : '''
// No default surface tint color'''}
${_elevationColor("$tokenGroup.container.surface-tint-layer.color")};
@override
MaterialStateProperty<double>? get elevation =>${_elevation()};
@override
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(_scaledPadding(context));
MaterialStatePropertyAll<EdgeInsetsGeometry>(_scaledPadding(context));
@override
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
@override
MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite);
const MaterialStatePropertyAll<Size>(Size.infinite);
${tokens.containsKey("$tokenGroup.outline.color") ? '''
@override
Expand All @@ -138,7 +142,7 @@ ${tokens.containsKey("$tokenGroup.outline.color") ? '''
@override
MaterialStateProperty<OutlinedBorder>? get shape =>
ButtonStyleButton.allOrNull<OutlinedBorder>(${shape("$tokenGroup.container")});
const MaterialStatePropertyAll<OutlinedBorder>(${shape("$tokenGroup.container", '')});
@override
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
Expand Down
4 changes: 2 additions & 2 deletions dev/tools/gen_defaults/lib/card_template.dart
Expand Up @@ -25,10 +25,10 @@ class _${blockName}DefaultsM3 extends CardTheme {
Color? get color => ${componentColor("md.comp.elevated-card.container")};
@override
Color? get shadowColor => ${color("md.comp.elevated-card.container.shadow-color")};
Color? get shadowColor => ${colorOrTransparent("md.comp.elevated-card.container.shadow-color")};
@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")};
}
''';
}
9 changes: 7 additions & 2 deletions dev/tools/gen_defaults/lib/dialog_template.dart
Expand Up @@ -27,9 +27,14 @@ class _${blockName}DefaultsM3 extends DialogTheme {
@override
Color? get iconColor => _colors.secondary;
// TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160
@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
TextStyle? get titleTextStyle => ${textStyle("md.comp.dialog.headline")};
Expand Down
4 changes: 2 additions & 2 deletions dev/tools/gen_defaults/lib/filter_chip_template.dart
Expand Up @@ -31,10 +31,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override
Color? get selectedColor => isEnabled
Expand Down
33 changes: 23 additions & 10 deletions dev/tools/gen_defaults/lib/icon_button_template.dart
Expand Up @@ -9,6 +9,15 @@ class IconButtonTemplate extends TokenTemplate {
super.colorSchemePrefix = '_colors.',
});


String _elevationColor(String token) {
if (tokens.containsKey(token)) {
return 'MaterialStatePropertyAll<Color>(${color(token)})';
} else {
return 'const MaterialStatePropertyAll<Color>(Colors.transparent)';
}
}

@override
String generate() => '''
class _${blockName}DefaultsM3 extends ButtonStyle {
Expand All @@ -26,7 +35,7 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
@override
MaterialStateProperty<Color?>? get backgroundColor =>
ButtonStyleButton.allOrNull<Color>(Colors.transparent);
const MaterialStatePropertyAll<Color?>(Colors.transparent);
@override
MaterialStateProperty<Color?>? get foregroundColor =>
Expand Down Expand Up @@ -66,37 +75,41 @@ class _${blockName}DefaultsM3 extends ButtonStyle {
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
MaterialStateProperty<double>? get elevation =>
ButtonStyleButton.allOrNull<double>(0.0);
MaterialStateProperty<Color>? get surfaceTintColor =>
${_elevationColor("md.comp.icon-button.container.surface-tint-layer.color")};
@override
MaterialStateProperty<EdgeInsetsGeometry>? get padding =>
ButtonStyleButton.allOrNull<EdgeInsetsGeometry>(const EdgeInsets.all(8.0));
const MaterialStatePropertyAll<EdgeInsetsGeometry>(EdgeInsets.all(8.0));
@override
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
@override
MaterialStateProperty<Size>? get maximumSize =>
ButtonStyleButton.allOrNull<Size>(Size.infinite);
const MaterialStatePropertyAll<Size>(Size.infinite);
@override
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
@override
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
MaterialStateProperty<MouseCursor?>? get mouseCursor =>
Expand Down
4 changes: 2 additions & 2 deletions dev/tools/gen_defaults/lib/input_chip_template.dart
Expand Up @@ -30,10 +30,10 @@ class _${blockName}DefaultsM3 extends ChipThemeData {
Color? get backgroundColor => ${componentColor("$tokenGroup$variant.container")};
@override
Color? get shadowColor => ${color("$tokenGroup.container.shadow-color")};
Color? get shadowColor => ${colorOrTransparent("$tokenGroup.container.shadow-color")};
@override
@override Color? get surfaceTintColor => ${color("$tokenGroup.container.surface-tint-layer.color")};
Color? get surfaceTintColor => ${colorOrTransparent("$tokenGroup.container.surface-tint-layer.color")};
@override
Color? get selectedColor => ${componentColor("$tokenGroup$variant.selected.container")};
Expand Down
4 changes: 3 additions & 1 deletion dev/tools/gen_defaults/lib/navigation_bar_template.dart
Expand Up @@ -26,7 +26,9 @@ class _${blockName}DefaultsM3 extends NavigationBarThemeData {
@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 {
return MaterialStateProperty.resolveWith((Set<MaterialState> states) {
Expand Down
24 changes: 18 additions & 6 deletions dev/tools/gen_defaults/lib/template.dart
Expand Up @@ -97,16 +97,28 @@ abstract class TokenTemplate {
/// If there is a value for the given token, this will return
/// the value prepended with [colorSchemePrefix].
///
/// Otherwise it will return 'null'.
/// Otherwise it will return [defaultValue].
///
/// See also:
/// * [componentColor], that provides support for an optional opacity.
String color(String colorToken) {
String color(String colorToken, [String defaultValue = 'null']) {
return tokens.containsKey(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
/// with opacity if available.
///
Expand Down Expand Up @@ -154,18 +166,18 @@ abstract class TokenTemplate {
/// Currently supports family:
/// - "SHAPE_FAMILY_ROUNDED_CORNERS" which maps to [RoundedRectangleBorder].
/// - "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>;
switch (shape['family']) {
case 'SHAPE_FAMILY_ROUNDED_CORNERS':
return 'const RoundedRectangleBorder(borderRadius: '
return '${prefix}RoundedRectangleBorder(borderRadius: '
'BorderRadius.only('
'topLeft: Radius.circular(${shape['topLeft']}), '
'topRight: Radius.circular(${shape['topRight']}), '
'bottomLeft: Radius.circular(${shape['bottomLeft']}), '
'bottomRight: Radius.circular(${shape['bottomRight']})))';
case 'SHAPE_FAMILY_CIRCULAR':
return 'const StadiumBorder()';
return '${prefix}StadiumBorder()';
}
print('Unsupported shape family type: ${shape['family']} for $componentToken');
return '';
Expand Down
2 changes: 1 addition & 1 deletion examples/api/test/material/appbar/app_bar.1_test.dart
Expand Up @@ -16,7 +16,7 @@ void main() {

expect(find.widgetWithText(AppBar, 'AppBar Demo'), findsOneWidget);
Material appbarMaterial = _getAppBarMaterial(tester);
expect(appbarMaterial.shadowColor, null);
expect(appbarMaterial.shadowColor, Colors.transparent);
expect(appbarMaterial.elevation, 0);

await tester.drag(find.text('Item 4'), _kOffset, touchSlopY: 0, warnIfMissed: false);
Expand Down
5 changes: 3 additions & 2 deletions packages/flutter/lib/src/material/action_chip.dart
Expand Up @@ -7,6 +7,7 @@ import 'package:flutter/widgets.dart';

import 'chip.dart';
import 'chip_theme.dart';
import 'colors.dart';
import 'debug.dart';
import 'theme.dart';
import 'theme_data.dart';
Expand Down Expand Up @@ -196,10 +197,10 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
Color? get backgroundColor => null;

@override
Color? get shadowColor => null;
Color? get shadowColor => Colors.transparent;

@override
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;

@override
Color? get selectedColor => null;
Expand Down
4 changes: 4 additions & 0 deletions packages/flutter/lib/src/material/app_bar.dart
Expand Up @@ -12,6 +12,7 @@ import 'package:flutter/widgets.dart';
import 'app_bar_theme.dart';
import 'back_button.dart';
import 'color_scheme.dart';
import 'colors.dart';
import 'constants.dart';
import 'debug.dart';
import 'flexible_space_bar.dart';
Expand Down Expand Up @@ -2370,6 +2371,9 @@ class _AppBarDefaultsM3 extends AppBarTheme {
@override
Color? get foregroundColor => _colors.onSurface;

@override
Color? get shadowColor => Colors.transparent;

@override
Color? get surfaceTintColor => _colors.surfaceTint;

Expand Down
2 changes: 1 addition & 1 deletion packages/flutter/lib/src/material/choice_chip.dart
Expand Up @@ -213,7 +213,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
Color? get shadowColor => Theme.of(context).colorScheme.shadow;

@override
@override Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;

@override
Color? get selectedColor => isEnabled
Expand Down

0 comments on commit 33ed6a3

Please sign in to comment.