API to generate a ColorScheme from a single seed color. (#93463)

This commit is contained in:
Darren Austin 2021-12-03 14:29:05 -08:00 committed by GitHub
parent 818f5caf38
commit 8630315aad
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 466 additions and 12 deletions

View file

@ -4,19 +4,51 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:material_color_utilities/material_color_utilities.dart';
import 'colors.dart';
import 'theme_data.dart';
/// A set of colors based on the
/// A set of 25 colors based on the
/// [Material spec](https://m3.material.io/styles/color/the-color-system/color-roles)
/// that can be used to configure the color properties of most components.
///
/// The [Theme] has a color scheme, [ThemeData.colorScheme], which is constructed
/// with [ColorScheme.fromSwatch].
/// The main accent color groups in the scheme are [primary], [secondary],
/// and [tertiary].
///
/// * Primary colors are used for key components across the UI, such as the FAB,
/// prominent buttons, and active states.
///
/// * Secondary colors are used for less prominent components in the UI, such as
/// filter chips, while expanding the opportunity for color expression.
///
/// * Tertiary colors are used for contrasting accents that can be used to
/// balance primary and secondary colors or bring heightened attention to
/// an element, such as an input field. The tertiary colors are left
/// for makers to use at their discretion and are intended to support
/// broader color expression in products.
///
/// The remaining colors of the scheme are comprised of neutral colors used for
/// backgrounds and surfaces, as well as specific colors for errors, dividers
/// and shadows.
///
/// Many of the colors have matching 'on' colors, which are used for drawing
/// content on top of the matching color. For example, if something is using
/// [primary] for a background color, [onPrimary] would be used to paint text
/// and icons on top of it. For this reason, the 'on' colors should have a
/// contrast ratio with their matching colors of at least 4.5:1 in order to
/// be readable.
///
/// The [Theme] has a color scheme, [ThemeData.colorScheme], which can either be
/// passed in as a parameter to the constructor or by using 'brightness' and
/// 'colorSchemeSeed' parameters (which are used to generate a scheme with
/// [ColorScheme.fromSeed]).
@immutable
class ColorScheme with Diagnosticable {
/// Create a ColorScheme instance.
/// Create a ColorScheme instance from the given colors.
///
/// [ColorScheme.fromSeed] can be used as a simpler way to create a full
/// color scheme derived from a single seed color.
///
/// For the color parameters that are nullable, it is still recommended
/// that applications provide values for them. They are only nullable due
@ -24,9 +56,25 @@ class ColorScheme with Diagnosticable {
///
/// If a color is not provided, the closest fallback color from the given
/// colors will be used for it (e.g. [primaryContainer] will default
/// to [primary]). Material 3 makes use of these colors for many component
/// defaults, so for the best results the application should supply colors
/// for all the parameters.
/// to [primary]). Material Design 3 makes use of these colors for many
/// component defaults, so for the best results the application should
/// supply colors for all the parameters. An easy way to ensure this is to
/// use [ColorScheme.fromSeed] to generate a full set of colors.
///
/// During the migration to Material Design 3, if an app's
/// [ThemeData.useMaterial3] is false, then components will only
/// use the following colors for defaults:
///
/// * [primary]
/// * [onPrimary]
/// * [secondary]
/// * [onSecondary]
/// * [error]
/// * [onError]
/// * [background]
/// * [onBackground]
/// * [surface]
/// * [onSurface]
const ColorScheme({
required this.brightness,
required this.primary,
@ -97,6 +145,127 @@ class ColorScheme with Diagnosticable {
_primaryVariant = primaryVariant,
_secondaryVariant = secondaryVariant;
/// Generate a [ColorScheme] derived from the given `seedColor`.
///
/// Using the seedColor as a starting point, a set of tonal palettes are
/// constructed. These tonal palettes are based on the Material 3 Color
/// system and provide all the needed colors for a [ColorScheme]. These
/// colors are designed to work well together and meet contrast
/// requirements for accessibility.
///
/// If any of the optional color parameters are non-null they will be
/// used in place of the generated colors for that field in the resulting
/// color scheme. This allows apps to override specific colors for their
/// needs.
///
/// Given the nature of the algorithm, the seedColor may not wind up as
/// one of the ColorScheme colors.
///
/// See also:
///
/// * <https://m3.material.io/styles/color/the-color-system/color-roles>, the
/// Material 3 Color system specification.
/// * <https://pub.dev/packages/material_color_utilities>, the package
/// used to generate the tonal palettes needed for the scheme.
factory ColorScheme.fromSeed({
required Color seedColor,
Brightness brightness = Brightness.light,
Color? primary,
Color? onPrimary,
Color? primaryContainer,
Color? onPrimaryContainer,
Color? secondary,
Color? onSecondary,
Color? secondaryContainer,
Color? onSecondaryContainer,
Color? tertiary,
Color? onTertiary,
Color? tertiaryContainer,
Color? onTertiaryContainer,
Color? error,
Color? onError,
Color? errorContainer,
Color? onErrorContainer,
Color? outline,
Color? background,
Color? onBackground,
Color? surface,
Color? onSurface,
Color? surfaceVariant,
Color? onSurfaceVariant,
Color? inverseSurface,
Color? onInverseSurface,
Color? inversePrimary,
Color? shadow,
}) {
final CorePalette palette = CorePalette.of(seedColor.value);
switch (brightness) {
case Brightness.light:
return ColorScheme(
primary: primary ?? Color(palette.primary.get(40)),
onPrimary: onPrimary ?? Color(palette.primary.get(100)),
primaryContainer: primaryContainer ?? Color(palette.primary.get(90)),
onPrimaryContainer: onPrimaryContainer ?? Color(palette.primary.get(10)),
secondary: secondary ?? Color(palette.secondary.get(40)),
onSecondary: onSecondary ?? Color(palette.secondary.get(100)),
secondaryContainer: secondaryContainer ?? Color(palette.secondary.get(90)),
onSecondaryContainer: onSecondaryContainer ?? Color(palette.secondary.get(10)),
tertiary: tertiary ?? Color(palette.tertiary.get(40)),
onTertiary: onTertiary ?? Color(palette.tertiary.get(100)),
tertiaryContainer: tertiaryContainer ?? Color(palette.tertiary.get(90)),
onTertiaryContainer: onTertiaryContainer ?? Color(palette.tertiary.get(10)),
error: error ?? Color(palette.error.get(40)),
onError: onError ?? Color(palette.error.get(100)),
errorContainer: errorContainer ?? Color(palette.error.get(90)),
onErrorContainer: onErrorContainer ?? Color(palette.error.get(10)),
outline: outline ?? Color(palette.neutralVariant.get(50)),
background: background ?? Color(palette.neutral.get(90)),
onBackground: onBackground ?? Color(palette.neutral.get(10)),
surface: surface ?? Color(palette.neutral.get(99)),
onSurface: onSurface ?? Color(palette.neutral.get(0)),
surfaceVariant: surfaceVariant ?? Color(palette.neutralVariant.get(90)),
onSurfaceVariant: onSurfaceVariant ?? Color(palette.neutralVariant.get(30)),
inverseSurface: inverseSurface ?? Color(palette.neutral.get(20)),
onInverseSurface: onInverseSurface ?? Color(palette.neutral.get(95)),
inversePrimary: inversePrimary ?? Color(palette.primary.get(80)),
shadow: shadow ?? Color(palette.neutral.get(0)),
brightness: brightness,
);
case Brightness.dark:
return ColorScheme(
primary: primary ?? Color(palette.primary.get(80)),
onPrimary: onPrimary ?? Color(palette.primary.get(20)),
primaryContainer: primaryContainer ?? Color(palette.primary.get(70)),
onPrimaryContainer: onPrimaryContainer ?? Color(palette.primary.get(10)),
secondary: secondary ?? Color(palette.secondary.get(80)),
onSecondary: onSecondary ?? Color(palette.secondary.get(20)),
secondaryContainer: secondaryContainer ?? Color(palette.secondary.get(70)),
onSecondaryContainer: onSecondaryContainer ?? Color(palette.secondary.get(10)),
tertiary: tertiary ?? Color(palette.tertiary.get(80)),
onTertiary: onTertiary ?? Color(palette.tertiary.get(20)),
tertiaryContainer: tertiaryContainer ?? Color(palette.tertiary.get(70)),
onTertiaryContainer: onTertiaryContainer ?? Color(palette.tertiary.get(10)),
error: error ?? Color(palette.error.get(80)),
onError: onError ?? Color(palette.error.get(20)),
errorContainer: errorContainer ?? Color(palette.error.get(70)),
onErrorContainer: onErrorContainer ?? Color(palette.error.get(10)),
outline: outline ?? Color(palette.neutralVariant.get(60)),
background: background ?? Color(palette.neutral.get(10)),
onBackground: onBackground ?? Color(palette.neutral.get(90)),
surface: surface ?? Color(palette.neutral.get(10)),
onSurface: onSurface ?? Color(palette.neutral.get(100)),
surfaceVariant: surfaceVariant ?? Color(palette.neutralVariant.get(30)),
onSurfaceVariant: onSurfaceVariant ?? Color(palette.neutralVariant.get(80)),
inverseSurface: inverseSurface ?? Color(palette.neutral.get(90)),
onInverseSurface: onInverseSurface ?? Color(palette.neutral.get(20)),
inversePrimary: inversePrimary ?? Color(palette.primary.get(40)),
shadow: shadow ?? Color(palette.neutral.get(0)),
brightness: brightness,
);
}
}
/// Create a ColorScheme based on a purple primary color that matches the
/// [baseline Material color scheme](https://material.io/design/color/the-color-system.html#color-theme-creation).
const ColorScheme.light({

View file

@ -200,13 +200,30 @@ enum MaterialTapTargetSize {
class ThemeData with Diagnosticable {
/// Create a [ThemeData] that's used to configure a [Theme].
///
/// Typically, only the [brightness], [primaryColor], or [primarySwatch] are
/// specified. That pair of values are used to construct the [colorScheme].
///
/// The [colorScheme] and [textTheme] are used by the Material components to
/// compute default values for visual properties. The API documentation for
/// each component widget explains exactly how the defaults are computed.
///
/// When providing a [ColorScheme], apps can either provide one directly
/// with the [colorScheme] parameter, or have one generated for them by
/// using the [colorSchemeSeed] and [brightness] parameters. A generated
/// color scheme will be based on the tones of [colorSchemeSeed] and all of
/// its contrasting color will meet accessibility guidelines for readability.
/// (See [ColorScheme.fromSeed] for more details.)
///
/// If the app wants to customize a generated color scheme, it can use
/// [ColorScheme.fromSeed] directly and then [ColorScheme.copyWith] on the
/// result to override any colors that need to be replaced. The result of
/// this can be used as the [colorScheme] directly.
///
/// For historical reasons, instead of using a [colorSchemeSeed] or
/// [colorScheme], you can provide either a [primaryColor] or [primarySwatch]
/// to construct the [colorScheme], but the results will not be as complete
/// as when using generation from a seed color.
///
/// If [colorSchemeSeed] is non-null then [colorScheme], [primaryColor] and
/// [primarySwatch] must all be null.
///
/// The [textTheme] [TextStyle] colors are black if the color scheme's
/// brightness is [Brightness.light], and white for [Brightness.dark].
///
@ -219,6 +236,7 @@ class ThemeData with Diagnosticable {
/// * [ThemeData.from], which creates a ThemeData from a [ColorScheme].
/// * [ThemeData.light], which creates a light blue theme.
/// * [ThemeData.dark], which creates dark theme with a teal secondary [ColorScheme] color.
/// * [ColorScheme.fromSeed], which is used to create a [ColorScheme] from a seed color.
factory ThemeData({
// GENERAL CONFIGURATION
AndroidOverscrollIndicator? androidOverscrollIndicator,
@ -234,9 +252,10 @@ class ThemeData with Diagnosticable {
bool? useMaterial3,
// COLOR
// [colorScheme] is the preferred way to configure colors. The other color
// properties (as well as brightness, primaryColorBrightness, and primarySwatch)
// properties (as well as primaryColorBrightness, and primarySwatch)
// will gradually be phased out, see https://github.com/flutter/flutter/issues/91772.
ColorScheme? colorScheme,
Color? colorSchemeSeed,
Brightness? brightness,
MaterialColor? primarySwatch,
Color? primaryColor,
@ -368,7 +387,6 @@ class ThemeData with Diagnosticable {
Brightness? primaryColorBrightness,
}) {
// GENERAL CONFIGURATION
applyElevationOverlayColor ??= false;
cupertinoOverrideTheme = cupertinoOverrideTheme?.noDefault();
inputDecorationTheme ??= const InputDecorationTheme();
platform ??= defaultTargetPlatform;
@ -392,8 +410,35 @@ class ThemeData with Diagnosticable {
// COLOR
assert(colorScheme?.brightness == null || brightness == null || colorScheme!.brightness == brightness);
assert(colorSchemeSeed == null || colorScheme == null);
assert(colorSchemeSeed == null || primarySwatch == null);
assert(colorSchemeSeed == null || primaryColor == null);
final Brightness _brightness = brightness ?? colorScheme?.brightness ?? Brightness.light;
final bool isDark = _brightness == Brightness.dark;
if (colorSchemeSeed != null) {
colorScheme = ColorScheme.fromSeed(seedColor: colorSchemeSeed, brightness: _brightness);
// For surfaces that use primary color in light themes and surface color in dark
final Color primarySurfaceColor = isDark ? colorScheme.surface : colorScheme.primary;
final Color onPrimarySurfaceColor = isDark ? colorScheme.onSurface : colorScheme.onPrimary;
// Default some of the color settings to values from the color scheme
primaryColor = primarySurfaceColor;
primaryColorBrightness = ThemeData.estimateBrightnessForColor(primarySurfaceColor);
canvasColor ??= colorScheme.background;
accentColor ??= colorScheme.secondary;
accentColorBrightness ??= ThemeData.estimateBrightnessForColor(colorScheme.secondary);
scaffoldBackgroundColor ??= colorScheme.background;
bottomAppBarColor ??= colorScheme.surface;
cardColor ??= colorScheme.surface;
dividerColor ??= colorScheme.outline;
backgroundColor ??= colorScheme.background;
dialogBackgroundColor ??= colorScheme.background;
indicatorColor ??= onPrimarySurfaceColor;
errorColor ??= colorScheme.error;
applyElevationOverlayColor ??= isDark;
}
applyElevationOverlayColor ??= false;
primarySwatch ??= Colors.blue;
primaryColor ??= isDark ? Colors.grey[900]! : primarySwatch;
final Brightness _primaryColorBrightness = estimateBrightnessForColor(primaryColor);

View file

@ -161,4 +161,139 @@ void main() {
expect(scheme.primaryVariant, const Color(0xffbe9eff));
expect(scheme.secondaryVariant, const Color(0xff66fff9));
});
test('can generate a light scheme from a seed color', () {
final ColorScheme scheme = ColorScheme.fromSeed(seedColor: Colors.blue);
expect(scheme.primary, const Color(0xff0061a6));
expect(scheme.onPrimary, const Color(0xffffffff));
expect(scheme.primaryContainer, const Color(0xffd0e4ff));
expect(scheme.onPrimaryContainer, const Color(0xff001d36));
expect(scheme.secondary, const Color(0xff535f70));
expect(scheme.onSecondary, const Color(0xffffffff));
expect(scheme.secondaryContainer, const Color(0xffd6e3f7));
expect(scheme.onSecondaryContainer, const Color(0xff101c2b));
expect(scheme.tertiary, const Color(0xff6b5778));
expect(scheme.onTertiary, const Color(0xffffffff));
expect(scheme.tertiaryContainer, const Color(0xfff3daff));
expect(scheme.onTertiaryContainer, const Color(0xff251432));
expect(scheme.error, const Color(0xffba1b1b));
expect(scheme.onError, const Color(0xffffffff));
expect(scheme.errorContainer, const Color(0xffffdad4));
expect(scheme.onErrorContainer, const Color(0xff410001));
expect(scheme.outline, const Color(0xff73777f));
expect(scheme.background, const Color(0xffe2e2e6));
expect(scheme.onBackground, const Color(0xff1b1b1b));
expect(scheme.surface, const Color(0xfffdfcff));
expect(scheme.onSurface, const Color(0xff000000));
expect(scheme.surfaceVariant, const Color(0xffdfe2eb));
expect(scheme.onSurfaceVariant, const Color(0xff42474e));
expect(scheme.inverseSurface, const Color(0xff2f3033));
expect(scheme.onInverseSurface, const Color(0xfff1f0f4));
expect(scheme.inversePrimary, const Color(0xff9ccaff));
expect(scheme.shadow, const Color(0xff000000));
expect(scheme.brightness, Brightness.light);
});
test('can generate a dark scheme from a seed color', () {
final ColorScheme scheme = ColorScheme.fromSeed(seedColor: Colors.blue, brightness: Brightness.dark);
expect(scheme.primary, const Color(0xff9ccaff));
expect(scheme.onPrimary, const Color(0xff00325a));
expect(scheme.primaryContainer, const Color(0xff60b0ff));
expect(scheme.onPrimaryContainer, const Color(0xff001d36));
expect(scheme.secondary, const Color(0xffbbc8db));
expect(scheme.onSecondary, const Color(0xff253140));
expect(scheme.secondaryContainer, const Color(0xff9facbf));
expect(scheme.onSecondaryContainer, const Color(0xff101c2b));
expect(scheme.tertiary, const Color(0xffd6bee4));
expect(scheme.onTertiary, const Color(0xff3b2948));
expect(scheme.tertiaryContainer, const Color(0xffbba3c9));
expect(scheme.onTertiaryContainer, const Color(0xff251432));
expect(scheme.error, const Color(0xffffb4a9));
expect(scheme.onError, const Color(0xff680003));
expect(scheme.errorContainer, const Color(0xffff897a));
expect(scheme.onErrorContainer, const Color(0xff410001));
expect(scheme.outline, const Color(0xff8d9199));
expect(scheme.background, const Color(0xff1b1b1b));
expect(scheme.onBackground, const Color(0xffe2e2e6));
expect(scheme.surface, const Color(0xff1b1b1b));
expect(scheme.onSurface, const Color(0xffffffff));
expect(scheme.surfaceVariant, const Color(0xff42474e));
expect(scheme.onSurfaceVariant, const Color(0xffc3c7d0));
expect(scheme.inverseSurface, const Color(0xffe2e2e6));
expect(scheme.onInverseSurface, const Color(0xff2f3033));
expect(scheme.inversePrimary, const Color(0xff0061a6));
expect(scheme.shadow, const Color(0xff000000));
expect(scheme.brightness, Brightness.dark);
});
test('can override specific colors in a generated scheme', () {
final ColorScheme baseScheme = ColorScheme.fromSeed(seedColor: Colors.blue);
const Color primaryOverride = Color(0xffabcdef);
final ColorScheme scheme = ColorScheme.fromSeed(
seedColor: Colors.blue,
primary: primaryOverride,
);
expect(scheme.primary, primaryOverride);
// The rest should be the same.
expect(scheme.onPrimary, baseScheme.onPrimary);
expect(scheme.primaryContainer, baseScheme.primaryContainer);
expect(scheme.onPrimaryContainer, baseScheme.onPrimaryContainer);
expect(scheme.secondary, baseScheme.secondary);
expect(scheme.onSecondary, baseScheme.onSecondary);
expect(scheme.secondaryContainer, baseScheme.secondaryContainer);
expect(scheme.onSecondaryContainer, baseScheme.onSecondaryContainer);
expect(scheme.tertiary, baseScheme.tertiary);
expect(scheme.onTertiary, baseScheme.onTertiary);
expect(scheme.tertiaryContainer, baseScheme.tertiaryContainer);
expect(scheme.onTertiaryContainer, baseScheme.onTertiaryContainer);
expect(scheme.error, baseScheme.error);
expect(scheme.onError, baseScheme.onError);
expect(scheme.errorContainer, baseScheme.errorContainer);
expect(scheme.onErrorContainer, baseScheme.onErrorContainer);
expect(scheme.outline, baseScheme.outline);
expect(scheme.background, baseScheme.background);
expect(scheme.onBackground, baseScheme.onBackground);
expect(scheme.surface, baseScheme.surface);
expect(scheme.onSurface, baseScheme.onSurface);
expect(scheme.surfaceVariant, baseScheme.surfaceVariant);
expect(scheme.onSurfaceVariant, baseScheme.onSurfaceVariant);
expect(scheme.inverseSurface, baseScheme.inverseSurface);
expect(scheme.onInverseSurface, baseScheme.onInverseSurface);
expect(scheme.inversePrimary, baseScheme.inversePrimary);
expect(scheme.shadow, baseScheme.shadow);
expect(scheme.brightness, baseScheme.brightness);
});
testWidgets('generated scheme "on" colors meet a11y contrast guidelines', (WidgetTester tester) async {
final ColorScheme colors = ColorScheme.fromSeed(seedColor: Colors.teal);
Widget label(String text, Color textColor, Color background) {
return Container(
color: background,
padding: const EdgeInsets.all(8),
child: Text(text, style: TextStyle(color: textColor)),
);
}
await tester.pumpWidget(
MaterialApp(
theme: ThemeData.from(colorScheme: colors),
home: Scaffold(
body: Column(
children: <Widget>[
label('primary', colors.onPrimary, colors.primary),
label('secondary', colors.onSecondary, colors.secondary),
label('tertiary', colors.onTertiary, colors.tertiary),
label('error', colors.onError, colors.error),
label('background', colors.onBackground, colors.background),
label('surface', colors.onSurface, colors.surface),
],
),
),
),
);
await expectLater(tester, meetsGuideline(textContrastGuideline));
},
skip: isBrowser, // https://github.com/flutter/flutter/issues/44115
);
}

View file

@ -130,6 +130,111 @@ void main() {
expect(const TextSelectionThemeData(cursorColor: Colors.red).cursorColor, Colors.red);
});
test('If colorSchemeSeed is used colorScheme, primaryColor and primarySwatch should not be.', () {
expect(() => ThemeData(colorSchemeSeed: Colors.blue, colorScheme: const ColorScheme.light()), throwsAssertionError);
expect(() => ThemeData(colorSchemeSeed: Colors.blue, primaryColor: Colors.green), throwsAssertionError);
expect(() => ThemeData(colorSchemeSeed: Colors.blue, primarySwatch: Colors.green), throwsAssertionError);
});
test('ThemeData can generate a light colorScheme from colorSchemeSeed', () {
final ThemeData theme = ThemeData(colorSchemeSeed: Colors.blue);
expect(theme.colorScheme.primary, const Color(0xff0061a6));
expect(theme.colorScheme.onPrimary, const Color(0xffffffff));
expect(theme.colorScheme.primaryContainer, const Color(0xffd0e4ff));
expect(theme.colorScheme.onPrimaryContainer, const Color(0xff001d36));
expect(theme.colorScheme.secondary, const Color(0xff535f70));
expect(theme.colorScheme.onSecondary, const Color(0xffffffff));
expect(theme.colorScheme.secondaryContainer, const Color(0xffd6e3f7));
expect(theme.colorScheme.onSecondaryContainer, const Color(0xff101c2b));
expect(theme.colorScheme.tertiary, const Color(0xff6b5778));
expect(theme.colorScheme.onTertiary, const Color(0xffffffff));
expect(theme.colorScheme.tertiaryContainer, const Color(0xfff3daff));
expect(theme.colorScheme.onTertiaryContainer, const Color(0xff251432));
expect(theme.colorScheme.error, const Color(0xffba1b1b));
expect(theme.colorScheme.onError, const Color(0xffffffff));
expect(theme.colorScheme.errorContainer, const Color(0xffffdad4));
expect(theme.colorScheme.onErrorContainer, const Color(0xff410001));
expect(theme.colorScheme.outline, const Color(0xff73777f));
expect(theme.colorScheme.background, const Color(0xffe2e2e6));
expect(theme.colorScheme.onBackground, const Color(0xff1b1b1b));
expect(theme.colorScheme.surface, const Color(0xfffdfcff));
expect(theme.colorScheme.onSurface, const Color(0xff000000));
expect(theme.colorScheme.surfaceVariant, const Color(0xffdfe2eb));
expect(theme.colorScheme.onSurfaceVariant, const Color(0xff42474e));
expect(theme.colorScheme.inverseSurface, const Color(0xff2f3033));
expect(theme.colorScheme.onInverseSurface, const Color(0xfff1f0f4));
expect(theme.colorScheme.inversePrimary, const Color(0xff9ccaff));
expect(theme.colorScheme.shadow, const Color(0xff000000));
expect(theme.colorScheme.brightness, Brightness.light);
expect(theme.primaryColor, theme.colorScheme.primary);
expect(theme.primaryColorBrightness, Brightness.dark);
expect(theme.canvasColor, theme.colorScheme.background);
expect(theme.accentColor, theme.colorScheme.secondary);
expect(theme.accentColorBrightness, Brightness.dark);
expect(theme.scaffoldBackgroundColor, theme.colorScheme.background);
expect(theme.bottomAppBarColor, theme.colorScheme.surface);
expect(theme.cardColor, theme.colorScheme.surface);
expect(theme.dividerColor, theme.colorScheme.outline);
expect(theme.backgroundColor, theme.colorScheme.background);
expect(theme.dialogBackgroundColor, theme.colorScheme.background);
expect(theme.indicatorColor, theme.colorScheme.onPrimary);
expect(theme.errorColor, theme.colorScheme.error);
expect(theme.applyElevationOverlayColor, false);
});
test('ThemeData can generate a dark colorScheme from colorSchemeSeed', () {
final ThemeData theme = ThemeData(
colorSchemeSeed: Colors.blue,
brightness: Brightness.dark,
);
expect(theme.colorScheme.primary, const Color(0xff9ccaff));
expect(theme.colorScheme.onPrimary, const Color(0xff00325a));
expect(theme.colorScheme.primaryContainer, const Color(0xff60b0ff));
expect(theme.colorScheme.onPrimaryContainer, const Color(0xff001d36));
expect(theme.colorScheme.secondary, const Color(0xffbbc8db));
expect(theme.colorScheme.onSecondary, const Color(0xff253140));
expect(theme.colorScheme.secondaryContainer, const Color(0xff9facbf));
expect(theme.colorScheme.onSecondaryContainer, const Color(0xff101c2b));
expect(theme.colorScheme.tertiary, const Color(0xffd6bee4));
expect(theme.colorScheme.onTertiary, const Color(0xff3b2948));
expect(theme.colorScheme.tertiaryContainer, const Color(0xffbba3c9));
expect(theme.colorScheme.onTertiaryContainer, const Color(0xff251432));
expect(theme.colorScheme.error, const Color(0xffffb4a9));
expect(theme.colorScheme.onError, const Color(0xff680003));
expect(theme.colorScheme.errorContainer, const Color(0xffff897a));
expect(theme.colorScheme.onErrorContainer, const Color(0xff410001));
expect(theme.colorScheme.outline, const Color(0xff8d9199));
expect(theme.colorScheme.background, const Color(0xff1b1b1b));
expect(theme.colorScheme.onBackground, const Color(0xffe2e2e6));
expect(theme.colorScheme.surface, const Color(0xff1b1b1b));
expect(theme.colorScheme.onSurface, const Color(0xffffffff));
expect(theme.colorScheme.surfaceVariant, const Color(0xff42474e));
expect(theme.colorScheme.onSurfaceVariant, const Color(0xffc3c7d0));
expect(theme.colorScheme.inverseSurface, const Color(0xffe2e2e6));
expect(theme.colorScheme.onInverseSurface, const Color(0xff2f3033));
expect(theme.colorScheme.inversePrimary, const Color(0xff0061a6));
expect(theme.colorScheme.shadow, const Color(0xff000000));
expect(theme.colorScheme.brightness, Brightness.dark);
expect(theme.primaryColor, theme.colorScheme.surface);
expect(theme.primaryColorBrightness, Brightness.dark);
expect(theme.canvasColor, theme.colorScheme.background);
expect(theme.accentColor, theme.colorScheme.secondary);
expect(theme.accentColorBrightness, Brightness.light);
expect(theme.scaffoldBackgroundColor, theme.colorScheme.background);
expect(theme.bottomAppBarColor, theme.colorScheme.surface);
expect(theme.cardColor, theme.colorScheme.surface);
expect(theme.dividerColor, theme.colorScheme.outline);
expect(theme.backgroundColor, theme.colorScheme.background);
expect(theme.dialogBackgroundColor, theme.colorScheme.background);
expect(theme.indicatorColor, theme.colorScheme.onSurface);
expect(theme.errorColor, theme.colorScheme.error);
expect(theme.applyElevationOverlayColor, true);
});
testWidgets('ThemeData.from a light color scheme sets appropriate values', (WidgetTester tester) async {
const ColorScheme lightColors = ColorScheme.light();
final ThemeData theme = ThemeData.from(colorScheme: lightColors);