Unverified Commit df110ef0 authored by Darren Austin's avatar Darren Austin Committed by GitHub

Provide Material 3 defaults for vanilla `Chip` widget. (#111597)

parent d0a1e9e3
...@@ -104,6 +104,7 @@ Future<void> main(List<String> args) async { ...@@ -104,6 +104,7 @@ Future<void> main(List<String> args) async {
tokens['colorsLight'] = _readTokenFile('color_light.json'); tokens['colorsLight'] = _readTokenFile('color_light.json');
tokens['colorsDark'] = _readTokenFile('color_dark.json'); tokens['colorsDark'] = _readTokenFile('color_dark.json');
ActionChipTemplate('Chip', '$materialLib/chip.dart', tokens).updateFile();
ActionChipTemplate('ActionChip', '$materialLib/action_chip.dart', tokens).updateFile(); ActionChipTemplate('ActionChip', '$materialLib/action_chip.dart', tokens).updateFile();
AppBarTemplate('AppBar', '$materialLib/app_bar.dart', tokens).updateFile(); AppBarTemplate('AppBar', '$materialLib/app_bar.dart', tokens).updateFile();
BannerTemplate('Banner', '$materialLib/banner.dart', tokens).updateFile(); BannerTemplate('Banner', '$materialLib/banner.dart', tokens).updateFile();
......
...@@ -170,6 +170,13 @@ abstract class TokenTemplate { ...@@ -170,6 +170,13 @@ abstract class TokenTemplate {
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':
final double topLeft = shape['topLeft'] as double;
final double topRight = shape['topRight'] as double;
final double bottomLeft = shape['bottomLeft'] as double;
final double bottomRight = shape['bottomRight'] as double;
if (topLeft == topRight && topLeft == bottomLeft && topLeft == bottomRight) {
return '${prefix}RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular($topLeft)))';
}
return '${prefix}RoundedRectangleBorder(borderRadius: ' return '${prefix}RoundedRectangleBorder(borderRadius: '
'BorderRadius.only(' 'BorderRadius.only('
'topLeft: Radius.circular(${shape['topLeft']}), ' 'topLeft: Radius.circular(${shape['topLeft']}), '
......
...@@ -184,7 +184,7 @@ class _ActionChipDefaultsM3 extends ChipThemeData { ...@@ -184,7 +184,7 @@ class _ActionChipDefaultsM3 extends ChipThemeData {
const _ActionChipDefaultsM3(this.context, this.isEnabled) const _ActionChipDefaultsM3(this.context, this.isEnabled)
: super( : super(
elevation: 0.0, elevation: 0.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
showCheckmark: true, showCheckmark: true,
); );
......
...@@ -223,7 +223,7 @@ class _CardDefaultsM3 extends CardTheme { ...@@ -223,7 +223,7 @@ class _CardDefaultsM3 extends CardTheme {
clipBehavior: Clip.none, clipBehavior: Clip.none,
elevation: 1.0, elevation: 1.0,
margin: const EdgeInsets.all(4.0), margin: const EdgeInsets.all(4.0),
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(12.0), topRight: Radius.circular(12.0), bottomLeft: Radius.circular(12.0), bottomRight: Radius.circular(12.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))),
); );
final BuildContext context; final BuildContext context;
......
...@@ -1164,11 +1164,15 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid ...@@ -1164,11 +1164,15 @@ class _RawChipState extends State<RawChip> with MaterialStateMixin, TickerProvid
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final ChipThemeData chipTheme = ChipTheme.of(context); final ChipThemeData chipTheme = ChipTheme.of(context);
final Brightness brightness = chipTheme.brightness ?? theme.brightness; final Brightness brightness = chipTheme.brightness ?? theme.brightness;
final ChipThemeData chipDefaults = widget.defaultProperties ?? ChipThemeData.fromDefaults( final ChipThemeData chipDefaults = widget.defaultProperties ??
brightness: brightness, (theme.useMaterial3
secondaryColor: brightness == Brightness.dark ? Colors.tealAccent[200]! : theme.primaryColor, ? _ChipDefaultsM3(context, widget.isEnabled)
labelStyle: theme.textTheme.bodyLarge!, : ChipThemeData.fromDefaults(
); brightness: brightness,
secondaryColor: brightness == Brightness.dark ? Colors.tealAccent[200]! : theme.primaryColor,
labelStyle: theme.textTheme.bodyLarge!,
)
);
final TextDirection? textDirection = Directionality.maybeOf(context); final TextDirection? textDirection = Directionality.maybeOf(context);
final OutlinedBorder resolvedShape = _getShape(theme, chipTheme, chipDefaults); final OutlinedBorder resolvedShape = _getShape(theme, chipTheme, chipDefaults);
...@@ -2184,3 +2188,77 @@ bool _hitIsOnDeleteIcon({ ...@@ -2184,3 +2188,77 @@ bool _hitIsOnDeleteIcon({
return adjustedPosition.dx <= accessibleDeleteButtonWidth; return adjustedPosition.dx <= accessibleDeleteButtonWidth;
} }
} }
// BEGIN GENERATED TOKEN PROPERTIES - Chip
// Do not edit by hand. The code between the "BEGIN GENERATED" and
// "END GENERATED" comments are generated from data in the Material
// Design token database by the script:
// dev/tools/gen_defaults/bin/gen_defaults.dart.
// Token database version: v0_127
class _ChipDefaultsM3 extends ChipThemeData {
const _ChipDefaultsM3(this.context, this.isEnabled)
: super(
elevation: 0.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
showCheckmark: true,
);
final BuildContext context;
final bool isEnabled;
@override
TextStyle? get labelStyle => Theme.of(context).textTheme.labelLarge;
@override
Color? get backgroundColor => null;
@override
Color? get shadowColor => Colors.transparent;
@override
Color? get surfaceTintColor => Theme.of(context).colorScheme.surfaceTint;
@override
Color? get selectedColor => null;
@override
Color? get checkmarkColor => null;
@override
Color? get disabledColor => null;
@override
Color? get deleteIconColor => null;
@override
BorderSide? get side => isEnabled
? BorderSide(color: Theme.of(context).colorScheme.outline)
: BorderSide(color: Theme.of(context).colorScheme.onSurface.withOpacity(0.12));
@override
IconThemeData? get iconTheme => IconThemeData(
color: isEnabled
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onSurface,
size: 18.0,
);
@override
EdgeInsetsGeometry? get padding => const EdgeInsets.all(8.0);
/// The chip at text scale 1 starts with 8px on each side and as text scaling
/// gets closer to 2 the label padding is linearly interpolated from 8px to 4px.
/// Once the widget has a text scaling of 2 or higher than the label padding
/// remains 4px.
@override
EdgeInsetsGeometry? get labelPadding => EdgeInsets.lerp(
const EdgeInsets.symmetric(horizontal: 8.0),
const EdgeInsets.symmetric(horizontal: 4.0),
clampDouble(MediaQuery.of(context).textScaleFactor - 1.0, 0.0, 1.0),
)!;
}
// END GENERATED TOKEN PROPERTIES - Chip
...@@ -195,7 +195,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData { ...@@ -195,7 +195,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
const _FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected) const _FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
: super( : super(
elevation: 0.0, elevation: 0.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
showCheckmark: true, showCheckmark: true,
); );
......
...@@ -1396,7 +1396,7 @@ class _DialogDefaultsM3 extends DialogTheme { ...@@ -1396,7 +1396,7 @@ class _DialogDefaultsM3 extends DialogTheme {
: super( : super(
alignment: Alignment.center, alignment: Alignment.center,
elevation: 6.0, elevation: 6.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(28.0), topRight: Radius.circular(28.0), bottomLeft: Radius.circular(28.0), bottomRight: Radius.circular(28.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0))),
); );
final BuildContext context; final BuildContext context;
......
...@@ -204,7 +204,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData { ...@@ -204,7 +204,7 @@ class _FilterChipDefaultsM3 extends ChipThemeData {
const _FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected) const _FilterChipDefaultsM3(this.context, this.isEnabled, this.isSelected)
: super( : super(
elevation: 0.0, elevation: 0.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
showCheckmark: true, showCheckmark: true,
); );
......
...@@ -850,13 +850,13 @@ class _FABDefaultsM3 extends FloatingActionButtonThemeData { ...@@ -850,13 +850,13 @@ class _FABDefaultsM3 extends FloatingActionButtonThemeData {
ShapeBorder? get shape { ShapeBorder? get shape {
switch (type) { switch (type) {
case _FloatingActionButtonType.regular: case _FloatingActionButtonType.regular:
return const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), bottomLeft: Radius.circular(16.0), bottomRight: Radius.circular(16.0))); return const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
case _FloatingActionButtonType.small: case _FloatingActionButtonType.small:
return const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(12.0), topRight: Radius.circular(12.0), bottomLeft: Radius.circular(12.0), bottomRight: Radius.circular(12.0))); return const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0)));
case _FloatingActionButtonType.large: case _FloatingActionButtonType.large:
return const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(28.0), topRight: Radius.circular(28.0), bottomLeft: Radius.circular(28.0), bottomRight: Radius.circular(28.0))); return const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(28.0)));
case _FloatingActionButtonType.extended: case _FloatingActionButtonType.extended:
return const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(16.0), topRight: Radius.circular(16.0), bottomLeft: Radius.circular(16.0), bottomRight: Radius.circular(16.0))); return const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
} }
} }
......
...@@ -255,7 +255,7 @@ class _InputChipDefaultsM3 extends ChipThemeData { ...@@ -255,7 +255,7 @@ class _InputChipDefaultsM3 extends ChipThemeData {
const _InputChipDefaultsM3(this.context, this.isEnabled) const _InputChipDefaultsM3(this.context, this.isEnabled)
: super( : super(
elevation: 0.0, elevation: 0.0,
shape: const RoundedRectangleBorder(borderRadius: BorderRadius.only(topLeft: Radius.circular(8.0), topRight: Radius.circular(8.0), bottomLeft: Radius.circular(8.0), bottomRight: Radius.circular(8.0))), shape: const RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
showCheckmark: true, showCheckmark: true,
); );
......
...@@ -215,7 +215,7 @@ Finder findTooltipContainer(String tooltipText) { ...@@ -215,7 +215,7 @@ Finder findTooltipContainer(String tooltipText) {
} }
void main() { void main() {
testWidgets('Chip defaults', (WidgetTester tester) async { testWidgets('M2 Chip defaults', (WidgetTester tester) async {
late TextTheme textTheme; late TextTheme textTheme;
Widget buildFrame(Brightness brightness) { Widget buildFrame(Brightness brightness) {
...@@ -292,6 +292,87 @@ void main() { ...@@ -292,6 +292,87 @@ void main() {
expect(labelStyle.wordSpacing, textTheme.bodyLarge?.wordSpacing); expect(labelStyle.wordSpacing, textTheme.bodyLarge?.wordSpacing);
}); });
testWidgets('M3 Chip defaults', (WidgetTester tester) async {
late TextTheme textTheme;
final ThemeData lightTheme = ThemeData.light(useMaterial3: true);
final ThemeData darkTheme = ThemeData.dark(useMaterial3: true);
Widget buildFrame(ThemeData theme) {
return MaterialApp(
theme: theme,
home: Scaffold(
body: Center(
child: Builder(
builder: (BuildContext context) {
textTheme = Theme.of(context).textTheme;
return Chip(
avatar: const CircleAvatar(child: Text('A')),
label: const Text('Chip A'),
onDeleted: () { },
);
},
),
),
),
);
}
await tester.pumpWidget(buildFrame(lightTheme));
expect(getMaterial(tester).color, null);
expect(getMaterial(tester).elevation, 0);
expect(getMaterial(tester).shape, RoundedRectangleBorder(
side: BorderSide(color: lightTheme.colorScheme.outline),
borderRadius: BorderRadius.circular(8.0),
));
expect(getIconData(tester).color, lightTheme.colorScheme.primary);
expect(getIconData(tester).opacity, null);
expect(getIconData(tester).size, 18);
TextStyle labelStyle = getLabelStyle(tester, 'Chip A').style;
expect(labelStyle.color, textTheme.labelLarge?.color);
expect(labelStyle.fontFamily, textTheme.labelLarge?.fontFamily);
expect(labelStyle.fontFamilyFallback, textTheme.labelLarge?.fontFamilyFallback);
expect(labelStyle.fontFeatures, textTheme.labelLarge?.fontFeatures);
expect(labelStyle.fontSize, textTheme.labelLarge?.fontSize);
expect(labelStyle.fontStyle, textTheme.labelLarge?.fontStyle);
expect(labelStyle.fontWeight, textTheme.labelLarge?.fontWeight);
expect(labelStyle.height, textTheme.labelLarge?.height);
expect(labelStyle.inherit, textTheme.labelLarge?.inherit);
expect(labelStyle.leadingDistribution, textTheme.labelLarge?.leadingDistribution);
expect(labelStyle.letterSpacing, textTheme.labelLarge?.letterSpacing);
expect(labelStyle.overflow, textTheme.labelLarge?.overflow);
expect(labelStyle.textBaseline, textTheme.labelLarge?.textBaseline);
expect(labelStyle.wordSpacing, textTheme.labelLarge?.wordSpacing);
await tester.pumpWidget(buildFrame(darkTheme));
await tester.pumpAndSettle(); // Theme transition animation
expect(getMaterial(tester).color, null);
expect(getMaterial(tester).elevation, 0);
expect(getMaterial(tester).shape, RoundedRectangleBorder(
side: BorderSide(color: darkTheme.colorScheme.outline),
borderRadius: BorderRadius.circular(8.0),
));
expect(getIconData(tester).color, darkTheme.colorScheme.primary);
expect(getIconData(tester).opacity, null);
expect(getIconData(tester).size, 18);
labelStyle = getLabelStyle(tester, 'Chip A').style;
expect(labelStyle.color, textTheme.labelLarge?.color);
expect(labelStyle.fontFamily, textTheme.labelLarge?.fontFamily);
expect(labelStyle.fontFamilyFallback, textTheme.labelLarge?.fontFamilyFallback);
expect(labelStyle.fontFeatures, textTheme.labelLarge?.fontFeatures);
expect(labelStyle.fontSize, textTheme.labelLarge?.fontSize);
expect(labelStyle.fontStyle, textTheme.labelLarge?.fontStyle);
expect(labelStyle.fontWeight, textTheme.labelLarge?.fontWeight);
expect(labelStyle.height, textTheme.labelLarge?.height);
expect(labelStyle.inherit, textTheme.labelLarge?.inherit);
expect(labelStyle.leadingDistribution, textTheme.labelLarge?.leadingDistribution);
expect(labelStyle.letterSpacing, textTheme.labelLarge?.letterSpacing);
expect(labelStyle.overflow, textTheme.labelLarge?.overflow);
expect(labelStyle.textBaseline, textTheme.labelLarge?.textBaseline);
expect(labelStyle.wordSpacing, textTheme.labelLarge?.wordSpacing);
});
testWidgets('Chip control test', (WidgetTester tester) async { testWidgets('Chip control test', (WidgetTester tester) async {
final FeedbackTester feedback = FeedbackTester(); final FeedbackTester feedback = FeedbackTester();
final List<String> deletedChipLabels = <String>[]; final List<String> deletedChipLabels = <String>[];
......
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