Skip to content

Commit

Permalink
Add support for M3 motion (#129942)
Browse files Browse the repository at this point in the history
## Description

This adds support for M3 easing and duration tokens.

This PR includes these changes:
* Generation of duration and easing constants, in `Durations` and
`Easing`, respectively (`Curves` is already taken in the `animation`
library)
* Add 3 Dart fixes

Once this is merged, I'll migrate packages/plugins/customers and then
uncomment the deprecation notices for the 3 M2 curves, all of which have
1:1 replacements.

## Related Issues
 - Fixes #116525

## Tests
 - Added Dart fix tests

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel
on [Discord].

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#overview
[Tree Hygiene]: https://github.com/flutter/flutter/wiki/Tree-hygiene
[test-exempt]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/wiki/Tree-hygiene#handling-breaking-changes
[Discord]: https://github.com/flutter/flutter/wiki/Chat
  • Loading branch information
guidezpl committed Jul 19, 2023
1 parent b54e83e commit 0830a36
Show file tree
Hide file tree
Showing 10 changed files with 407 additions and 1 deletion.
2 changes: 2 additions & 0 deletions dev/tools/gen_defaults/bin/gen_defaults.dart
Expand Up @@ -37,6 +37,7 @@ import 'package:gen_defaults/input_chip_template.dart';
import 'package:gen_defaults/input_decorator_template.dart';
import 'package:gen_defaults/list_tile_template.dart';
import 'package:gen_defaults/menu_template.dart';
import 'package:gen_defaults/motion_template.dart';
import 'package:gen_defaults/navigation_bar_template.dart';
import 'package:gen_defaults/navigation_drawer_template.dart';
import 'package:gen_defaults/navigation_rail_template.dart';
Expand Down Expand Up @@ -131,6 +132,7 @@ Future<void> main(List<String> args) async {
ListTileTemplate('LisTile', '$materialLib/list_tile.dart', tokens).updateFile();
InputDecoratorTemplate('InputDecorator', '$materialLib/input_decorator.dart', tokens).updateFile();
MenuTemplate('Menu', '$materialLib/menu_anchor.dart', tokens).updateFile();
MotionTemplate('Motion', '$materialLib/motion.dart', tokens, tokenLogger).updateFile();
NavigationBarTemplate('NavigationBar', '$materialLib/navigation_bar.dart', tokens).updateFile();
NavigationDrawerTemplate('NavigationDrawer', '$materialLib/navigation_drawer.dart', tokens).updateFile();
NavigationRailTemplate('NavigationRail', '$materialLib/navigation_rail.dart', tokens).updateFile();
Expand Down
25 changes: 25 additions & 0 deletions dev/tools/gen_defaults/generated/used_tokens.csv
Expand Up @@ -856,6 +856,31 @@ md.sys.elevation.level2,
md.sys.elevation.level3,
md.sys.elevation.level4,
md.sys.elevation.level5,
md.sys.motion.duration.extra-long1Ms,
md.sys.motion.duration.extra-long2Ms,
md.sys.motion.duration.extra-long3Ms,
md.sys.motion.duration.extra-long4Ms,
md.sys.motion.duration.long1Ms,
md.sys.motion.duration.long2Ms,
md.sys.motion.duration.long3Ms,
md.sys.motion.duration.long4Ms,
md.sys.motion.duration.medium1Ms,
md.sys.motion.duration.medium2Ms,
md.sys.motion.duration.medium3Ms,
md.sys.motion.duration.medium4Ms,
md.sys.motion.duration.short1Ms,
md.sys.motion.duration.short2Ms,
md.sys.motion.duration.short3Ms,
md.sys.motion.duration.short4Ms,
md.sys.motion.easing.emphasized.accelerate,
md.sys.motion.easing.emphasized.decelerate,
md.sys.motion.easing.legacy,
md.sys.motion.easing.legacy.accelerate,
md.sys.motion.easing.legacy.decelerate,
md.sys.motion.easing.linear,
md.sys.motion.easing.standard,
md.sys.motion.easing.standard.accelerate,
md.sys.motion.easing.standard.decelerate,
md.sys.shape.corner.extra-large,
md.sys.shape.corner.extra-large.top,
md.sys.shape.corner.extra-small,
Expand Down
90 changes: 90 additions & 0 deletions dev/tools/gen_defaults/lib/motion_template.dart
@@ -0,0 +1,90 @@
// 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';
import 'token_logger.dart';

class MotionTemplate extends TokenTemplate {
/// Since we generate the tokens dynamically, we need to store them and log
/// them manually, instead of using [getToken].
MotionTemplate(String blockName, String fileName, this.tokens, this.tokensLogger) : super(blockName, fileName, tokens);
Map<String, dynamic> tokens;
TokenLogger tokensLogger;

// List of duration tokens.
late List<MapEntry<String, dynamic>> durationTokens = tokens.entries.where(
(MapEntry<String, dynamic> entry) => entry.key.contains('.duration.')
).toList()
..sort(
(MapEntry<String, dynamic> a, MapEntry<String, dynamic> b) => (a.value as double).compareTo(b.value as double)
);

// List of easing curve tokens.
late List<MapEntry<String, dynamic>> easingCurveTokens = tokens.entries.where(
(MapEntry<String, dynamic> entry) => entry.key.contains('.easing.')
).toList()
..sort(
// Sort the legacy curves at the end of the list.
(MapEntry<String, dynamic> a, MapEntry<String, dynamic> b) => a.key.contains('legacy') ? 1 : a.key.compareTo(b.key)
);

String durationTokenString(String token, dynamic tokenValue) {
tokensLogger.log(token);
final String tokenName = token.split('.').last.replaceAll('-', '').replaceFirst('Ms', '');
final int milliseconds = (tokenValue as double).toInt();
return
'''
/// The $tokenName duration (${milliseconds}ms) in the Material specification.
///
/// See also:
///
/// * [M3 guidelines: Duration tokens](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#c009dec6-f29b-4503-b9f0-482af14a8bbd)
/// * [M3 guidelines: Applying easing and duration](https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration)
static const Duration $tokenName = Duration(milliseconds: $milliseconds);
''';
}

String easingCurveTokenString(String token, dynamic tokenValue) {
tokensLogger.log(token);
final String tokenName = token
.replaceFirst('md.sys.motion.easing.', '')
.replaceAllMapped(RegExp(r'[-\.](\w)'), (Match match) {
return match.group(1)!.toUpperCase();
});
return '''
/// The $tokenName easing curve in the Material specification.
///
/// See also:
///
/// * [M3 guidelines: Easing tokens](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#433b1153-2ea3-4fe2-9748-803a47bc97ee)
/// * [M3 guidelines: Applying easing and duration](https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration)
static const Curve $tokenName = $tokenValue;
''';
}

@override
String generate() => '''
/// The set of durations in the Material specification.
///
/// See also:
///
/// * [M3 guidelines: Duration tokens](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#c009dec6-f29b-4503-b9f0-482af14a8bbd)
/// * [M3 guidelines: Applying easing and duration](https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration)
abstract final class Durations {
${durationTokens.map((MapEntry<String, dynamic> entry) => durationTokenString(entry.key, entry.value)).join('\n')}}
// TODO(guidezpl): Improve with description and assets, b/289870605
/// The set of easing curves in the Material specification.
///
/// See also:
///
/// * [M3 guidelines: Easing tokens](https://m3.material.io/styles/motion/easing-and-duration/tokens-specs#433b1153-2ea3-4fe2-9748-803a47bc97ee)
/// * [M3 guidelines: Applying easing and duration](https://m3.material.io/styles/motion/easing-and-duration/applying-easing-and-duration)
/// * [Curves], for a collection of non-Material animation easing curves.
abstract final class Easing {
${easingCurveTokens.map((MapEntry<String, dynamic> entry) => easingCurveTokenString(entry.key, entry.value)).join('\n')}}
''';
}
39 changes: 39 additions & 0 deletions packages/flutter/lib/fix_data/fix_material/fix_material.yaml
Expand Up @@ -897,4 +897,43 @@ transforms:
oldName: 'showTrackOnHover'
newName: 'trackVisibility'

# Changes made in https://github.com/flutter/flutter/pull/129942
- title: "Migrate to 'Easing.legacy'"
date: 2023-07-04
element:
uris: [ 'material.dart' ]
variable: 'standardEasing'
changes:
- kind: 'replacedBy'
newElement:
uris: [ 'material.dart' ]
field: legacy
inClass: Easing

# Changes made in https://github.com/flutter/flutter/pull/129942
- title: "Migrate to 'Easing.legacyAccelerate'"
date: 2023-07-04
element:
uris: [ 'material.dart' ]
variable: 'accelerateEasing'
changes:
- kind: 'replacedBy'
newElement:
uris: [ 'material.dart' ]
field: legacyAccelerate
inClass: Easing

# Changes made in https://github.com/flutter/flutter/pull/129942
- title: "Migrate to 'Easing.legacyDecelerate'"
date: 2023-07-04
element:
uris: [ 'material.dart' ]
variable: 'decelerateEasing'
changes:
- kind: 'replacedBy'
newElement:
uris: [ 'material.dart' ]
field: legacyDecelerate
inClass: Easing

# Before adding a new fix: read instructions at the top of this file.
1 change: 1 addition & 0 deletions packages/flutter/lib/material.dart
Expand Up @@ -122,6 +122,7 @@ export 'src/material/menu_button_theme.dart';
export 'src/material/menu_style.dart';
export 'src/material/menu_theme.dart';
export 'src/material/mergeable_material.dart';
export 'src/material/motion.dart';
export 'src/material/navigation_bar.dart';
export 'src/material/navigation_bar_theme.dart';
export 'src/material/navigation_drawer.dart';
Expand Down
3 changes: 2 additions & 1 deletion packages/flutter/lib/src/animation/curves.dart
Expand Up @@ -1354,6 +1354,7 @@ class ElasticInOutCurve extends Curve {
///
/// * [Curve], the interface implemented by the constants available from the
/// [Curves] class.
/// * [Easing], for the Material animation curves.
abstract final class Curves {
/// A linear animation curve.
///
Expand Down Expand Up @@ -1741,7 +1742,7 @@ abstract final class Curves {
///
/// See also:
///
/// * [standardEasing], the name for this curve in the Material specification.
/// * [Easing.legacy], the name for this curve in the Material specification.
static const Cubic fastOutSlowIn = Cubic(0.4, 0.0, 0.2, 1.0);

/// A cubic animation curve that starts quickly, slows down, and then ends
Expand Down
2 changes: 2 additions & 0 deletions packages/flutter/lib/src/material/curves.dart
Expand Up @@ -6,6 +6,8 @@ import 'package:flutter/animation.dart';

// The easing curves of the Material Library

// TODO(guidezpl): deprecate the three curves below once customers (packages/plugins) are migrated

/// The standard easing curve in the Material specification.
///
/// Elements that begin and end at rest use standard easing.
Expand Down

0 comments on commit 0830a36

Please sign in to comment.