Unverified Commit 93a1b7a5 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Material 3 Typography support. (#97829)

parent 26d4e927
......@@ -18,6 +18,7 @@ import 'dart:convert';
import 'dart:io';
import 'package:gen_defaults/fab_template.dart';
import 'package:gen_defaults/typography_template.dart';
Map<String, dynamic> _readTokenFile(String fileName) {
return jsonDecode(File('dev/tools/gen_defaults/data/$fileName').readAsStringSync()) as Map<String, dynamic>;
......@@ -70,4 +71,5 @@ Future<void> main(List<String> args) async {
}
FABTemplate('$materialLib/floating_action_button.dart', tokens).updateFile();
TypographyTemplate('$materialLib/typography.dart', tokens).updateFile();
}
......@@ -86,7 +86,6 @@ abstract class TokenTemplate {
}
String textStyle(String tokenName) {
final String fontName = '$tokenName.text-style';
return tokens[fontName]!.toString();
return tokens['$tokenName.text-style']!.toString();
}
}
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'template.dart';
class TypographyTemplate extends TokenTemplate {
const TypographyTemplate(String fileName, Map<String, dynamic> tokens) : super(fileName, tokens);
@override
String generate() => '''
// Generated version ${tokens["version"]}
class _M3Typography {
_M3Typography._();
${_textTheme('englishLike', 'alphabetic')}
${_textTheme('dense', 'ideographic')}
${_textTheme('tall', 'alphabetic')}
}
''';
String _textTheme(String name, String baseline) {
final StringBuffer theme = StringBuffer('static const TextTheme $name = TextTheme(\n');
theme.writeln(' displayLarge: ${_textStyleDef('md.sys.typescale.display-large', '$name displayLarge 2021', baseline)},');
theme.writeln(' displayMedium: ${_textStyleDef('md.sys.typescale.display-medium', '$name displayMedium 2021', baseline)},');
theme.writeln(' displaySmall: ${_textStyleDef('md.sys.typescale.display-small', '$name displaySmall 2021', baseline)},');
theme.writeln(' headlineLarge: ${_textStyleDef('md.sys.typescale.headline-large', '$name headlineLarge 2021', baseline)},');
theme.writeln(' headlineMedium: ${_textStyleDef('md.sys.typescale.headline-medium', '$name headlineMedium 2021', baseline)},');
theme.writeln(' headlineSmall: ${_textStyleDef('md.sys.typescale.headline-small', '$name headlineSmall 2021', baseline)},');
theme.writeln(' titleLarge: ${_textStyleDef('md.sys.typescale.title-large', '$name titleLarge 2021', baseline)},');
theme.writeln(' titleMedium: ${_textStyleDef('md.sys.typescale.title-medium', '$name titleMedium 2021', baseline)},');
theme.writeln(' titleSmall: ${_textStyleDef('md.sys.typescale.title-small', '$name titleSmall 2021', baseline)},');
theme.writeln(' labelLarge: ${_textStyleDef('md.sys.typescale.label-large', '$name labelLarge 2021', baseline)},');
theme.writeln(' labelMedium: ${_textStyleDef('md.sys.typescale.label-medium', '$name labelMedium 2021', baseline)},');
theme.writeln(' labelSmall: ${_textStyleDef('md.sys.typescale.label-small', '$name labelSmall 2021', baseline)},');
theme.writeln(' bodyLarge: ${_textStyleDef('md.sys.typescale.body-large', '$name bodyLarge 2021', baseline)},');
theme.writeln(' bodyMedium: ${_textStyleDef('md.sys.typescale.body-medium', '$name bodyMedium 2021', baseline)},');
theme.writeln(' bodySmall: ${_textStyleDef('md.sys.typescale.body-small', '$name bodySmall 2021', baseline)},');
theme.write(' );');
return theme.toString();
}
String _textStyleDef(String tokenName, String debugLabel, String baseline) {
final StringBuffer style = StringBuffer("TextStyle(debugLabel: '$debugLabel'");
style.write(', inherit: false');
style.write(', fontSize: ${_fontSize(tokenName)}');
style.write(', fontWeight: ${_fontWeight(tokenName)}');
style.write(', letterSpacing: ${_fontSpacing(tokenName)}');
style.write(', height: ${_fontHeight(tokenName)}');
style.write(', textBaseline: TextBaseline.$baseline');
style.write(', leadingDistribution: TextLeadingDistribution.even');
style.write(')');
return style.toString();
}
String _fontSize(String textStyleTokenName) {
return tokens['$textStyleTokenName.size']!.toString();
}
String _fontWeight(String textStyleTokenName) {
final String weightValue = tokens[tokens['$textStyleTokenName.weight']!]!.toString();
return 'FontWeight.w$weightValue';
}
String _fontSpacing(String textStyleTokenName) {
return tokens['$textStyleTokenName.tracking']!.toString();
}
String _fontHeight(String textStyleTokenName) {
final double size = tokens['$textStyleTokenName.size']! as double;
final double lineHeight = tokens['$textStyleTokenName.line-height']! as double;
return (lineHeight / size).toStringAsFixed(2);
}
}
......@@ -495,7 +495,7 @@ class ThemeData with Diagnosticable {
splashColor ??= isDark ? _kDarkThemeSplashColor : _kLightThemeSplashColor;
// TYPOGRAPHY & ICONOGRAPHY
typography ??= Typography.material2014(platform: platform);
typography ??= useMaterial3 ? Typography.material2021(platform: platform) : Typography.material2014(platform: platform);
TextTheme defaultTextTheme = isDark ? typography.white : typography.black;
TextTheme defaultPrimaryTextTheme = primaryIsDark ? typography.white : typography.black;
TextTheme defaultAccentTextTheme = accentIsDark ? typography.white : typography.black;
......@@ -1134,6 +1134,9 @@ class ThemeData with Diagnosticable {
/// start using new colors, typography and other features of Material 3.
/// If false, they will use the Material 2 look and feel.
///
/// If true, the default Typography will be [Typography.material2021],
/// otherwise it will default to [Typography.material2014].
///
/// During the migration to Material 3, turning this on may yield
/// inconsistent look and feel in your app. Some components will be migrated
/// before others and typography changes will be coming in stages.
......
......@@ -84,6 +84,11 @@ void main() {
);
});
testWidgets('ThemeData with null typography uses proper defaults', (WidgetTester tester) async {
expect(ThemeData().typography, Typography.material2014());
expect(ThemeData(useMaterial3: true).typography, Typography.material2021());
});
testWidgets('PopupMenu inherits shadowed app theme', (WidgetTester tester) async {
// Regression test for https://github.com/flutter/flutter/issues/5572
final Key popupMenuButtonKey = UniqueKey();
......
......@@ -200,4 +200,147 @@ void main() {
expect(theme.labelSmall!.fontSize, 10);
expect(theme.labelSmall!.letterSpacing, 1.5);
});
test('englishLike2021 TextTheme matches Material Design 3 spec', () {
// Check the default material text theme against the style values
// shown https://m3.material.io/styles/typography/tokens.
//
// This may need to be updated if the token values change.
final TextTheme theme = Typography.englishLike2021.merge(Typography.blackMountainView);
// Display large
expect(theme.displayLarge!.fontFamily, 'Roboto');
expect(theme.displayLarge!.fontSize, 57.0);
expect(theme.displayLarge!.fontWeight, FontWeight.w400);
expect(theme.displayLarge!.letterSpacing, -0.25);
expect(theme.displayLarge!.height, 1.12);
expect(theme.displayLarge!.textBaseline, TextBaseline.alphabetic);
expect(theme.displayLarge!.leadingDistribution, TextLeadingDistribution.even);
// Display medium
expect(theme.displayMedium!.fontFamily, 'Roboto');
expect(theme.displayMedium!.fontSize, 45.0);
expect(theme.displayMedium!.fontWeight, FontWeight.w400);
expect(theme.displayMedium!.letterSpacing, 0.0);
expect(theme.displayMedium!.height, 1.16);
expect(theme.displayMedium!.textBaseline, TextBaseline.alphabetic);
expect(theme.displayMedium!.leadingDistribution, TextLeadingDistribution.even);
// Display small
expect(theme.displaySmall!.fontFamily, 'Roboto');
expect(theme.displaySmall!.fontSize, 36.0);
expect(theme.displaySmall!.fontWeight, FontWeight.w400);
expect(theme.displaySmall!.letterSpacing, 0.0);
expect(theme.displaySmall!.height, 1.22);
expect(theme.displaySmall!.textBaseline, TextBaseline.alphabetic);
expect(theme.displaySmall!.leadingDistribution, TextLeadingDistribution.even);
// Headline large
expect(theme.headlineLarge!.fontFamily, 'Roboto');
expect(theme.headlineLarge!.fontSize, 32.0);
expect(theme.headlineLarge!.fontWeight, FontWeight.w400);
expect(theme.headlineLarge!.letterSpacing, 0.0);
expect(theme.headlineLarge!.height, 1.25);
expect(theme.headlineLarge!.textBaseline, TextBaseline.alphabetic);
expect(theme.headlineLarge!.leadingDistribution, TextLeadingDistribution.even);
// Headline medium
expect(theme.headlineMedium!.fontFamily, 'Roboto');
expect(theme.headlineMedium!.fontSize, 28.0);
expect(theme.headlineMedium!.fontWeight, FontWeight.w400);
expect(theme.headlineMedium!.letterSpacing, 0.0);
expect(theme.headlineMedium!.height, 1.29);
expect(theme.headlineMedium!.textBaseline, TextBaseline.alphabetic);
expect(theme.headlineMedium!.leadingDistribution, TextLeadingDistribution.even);
// Headline small
expect(theme.headlineSmall!.fontFamily, 'Roboto');
expect(theme.headlineSmall!.fontSize, 24.0);
expect(theme.headlineSmall!.fontWeight, FontWeight.w400);
expect(theme.headlineSmall!.letterSpacing, 0.0);
expect(theme.headlineSmall!.height, 1.33);
expect(theme.headlineSmall!.textBaseline, TextBaseline.alphabetic);
expect(theme.headlineSmall!.leadingDistribution, TextLeadingDistribution.even);
// Title large
expect(theme.titleLarge!.fontFamily, 'Roboto');
expect(theme.titleLarge!.fontSize, 22.0);
expect(theme.titleLarge!.fontWeight, FontWeight.w400);
expect(theme.titleLarge!.letterSpacing, 0.0);
expect(theme.titleLarge!.height, 1.27);
expect(theme.titleLarge!.textBaseline, TextBaseline.alphabetic);
expect(theme.titleLarge!.leadingDistribution, TextLeadingDistribution.even);
// Title medium
expect(theme.titleMedium!.fontFamily, 'Roboto');
expect(theme.titleMedium!.fontSize, 16.0);
expect(theme.titleMedium!.fontWeight, FontWeight.w500);
expect(theme.titleMedium!.letterSpacing, 0.15);
expect(theme.titleMedium!.height, 1.50);
expect(theme.titleMedium!.textBaseline, TextBaseline.alphabetic);
expect(theme.titleMedium!.leadingDistribution, TextLeadingDistribution.even);
// Title small
expect(theme.titleSmall!.fontFamily, 'Roboto');
expect(theme.titleSmall!.fontSize, 14.0);
expect(theme.titleSmall!.fontWeight, FontWeight.w500);
expect(theme.titleSmall!.letterSpacing, 0.1);
expect(theme.titleSmall!.height, 1.43);
expect(theme.titleSmall!.textBaseline, TextBaseline.alphabetic);
expect(theme.titleSmall!.leadingDistribution, TextLeadingDistribution.even);
// Label large
expect(theme.labelLarge!.fontFamily, 'Roboto');
expect(theme.labelLarge!.fontSize, 14.0);
expect(theme.labelLarge!.fontWeight, FontWeight.w500);
expect(theme.labelLarge!.letterSpacing, 0.1);
expect(theme.labelLarge!.height, 1.43);
expect(theme.labelLarge!.textBaseline, TextBaseline.alphabetic);
expect(theme.labelLarge!.leadingDistribution, TextLeadingDistribution.even);
// Label medium
expect(theme.labelMedium!.fontFamily, 'Roboto');
expect(theme.labelMedium!.fontSize, 12.0);
expect(theme.labelMedium!.fontWeight, FontWeight.w500);
expect(theme.labelMedium!.letterSpacing, 0.5);
expect(theme.labelMedium!.height, 1.33);
expect(theme.labelMedium!.textBaseline, TextBaseline.alphabetic);
expect(theme.labelMedium!.leadingDistribution, TextLeadingDistribution.even);
// Label small
expect(theme.labelSmall!.fontFamily, 'Roboto');
expect(theme.labelSmall!.fontSize, 11.0);
expect(theme.labelSmall!.fontWeight, FontWeight.w500);
expect(theme.labelSmall!.letterSpacing, 0.5);
expect(theme.labelSmall!.height, 1.45);
expect(theme.labelSmall!.textBaseline, TextBaseline.alphabetic);
expect(theme.labelSmall!.leadingDistribution, TextLeadingDistribution.even);
// Body large
expect(theme.bodyLarge!.fontFamily, 'Roboto');
expect(theme.bodyLarge!.fontSize, 16.0);
expect(theme.bodyLarge!.fontWeight, FontWeight.w400);
expect(theme.bodyLarge!.letterSpacing, 0.5);
expect(theme.bodyLarge!.height, 1.50);
expect(theme.bodyLarge!.textBaseline, TextBaseline.alphabetic);
expect(theme.bodyLarge!.leadingDistribution, TextLeadingDistribution.even);
// Body medium
expect(theme.bodyMedium!.fontFamily, 'Roboto');
expect(theme.bodyMedium!.fontSize, 14.0);
expect(theme.bodyMedium!.fontWeight, FontWeight.w400);
expect(theme.bodyMedium!.letterSpacing, 0.25);
expect(theme.bodyMedium!.height, 1.43);
expect(theme.bodyMedium!.textBaseline, TextBaseline.alphabetic);
expect(theme.bodyMedium!.leadingDistribution, TextLeadingDistribution.even);
// Body small
expect(theme.bodySmall!.fontFamily, 'Roboto');
expect(theme.bodySmall!.fontSize, 12.0);
expect(theme.bodySmall!.fontWeight, FontWeight.w400);
expect(theme.bodySmall!.letterSpacing, 0.4);
expect(theme.bodySmall!.height, 1.33);
expect(theme.bodySmall!.textBaseline, TextBaseline.alphabetic);
expect(theme.bodySmall!.leadingDistribution, TextLeadingDistribution.even);
});
}
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