Skip to content

Commit

Permalink
Fix M3 Drawer default shape in RTL (flutter#118185)
Browse files Browse the repository at this point in the history
  • Loading branch information
TahaTesser committed Jan 12, 2023
1 parent 51c2af5 commit 0d91c03
Show file tree
Hide file tree
Showing 3 changed files with 194 additions and 18 deletions.
23 changes: 14 additions & 9 deletions dev/tools/gen_defaults/lib/drawer_template.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ class DrawerTemplate extends TokenTemplate {
@override
String generate() => '''
class _${blockName}DefaultsM3 extends DrawerThemeData {
const _${blockName}DefaultsM3(this.context)
_${blockName}DefaultsM3(this.context)
: super(elevation: ${elevation("md.comp.navigation-drawer.modal.container")});
final BuildContext context;
late final TextDirection direction = Directionality.of(context);
@override
Color? get backgroundColor => ${componentColor("md.comp.navigation-drawer.container")};
Expand All @@ -24,18 +25,22 @@ class _${blockName}DefaultsM3 extends DrawerThemeData {
@override
Color? get shadowColor => ${colorOrTransparent("md.comp.navigation-drawer.container.shadow-color")};
// This don't appear to be tokens for this value, but it is
// shown in the spec.
// There isn't currently a token for this value, but it is shown in the spec,
// so hard coding here for now.
@override
ShapeBorder? get shape => const RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(right: Radius.circular(16.0)),
ShapeBorder? get shape => RoundedRectangleBorder(
borderRadius: const BorderRadiusDirectional.horizontal(
end: Radius.circular(16.0),
).resolve(direction),
);
// This don't appear to be tokens for this value, but it is
// shown in the spec.
// There isn't currently a token for this value, but it is shown in the spec,
// so hard coding here for now.
@override
ShapeBorder? get endShape => const RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(left: Radius.circular(16.0)),
ShapeBorder? get endShape => RoundedRectangleBorder(
borderRadius: const BorderRadiusDirectional.horizontal(
start: Radius.circular(16.0),
).resolve(direction),
);
}
''';
Expand Down
23 changes: 14 additions & 9 deletions packages/flutter/lib/src/material/drawer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -830,10 +830,11 @@ class _DrawerDefaultsM2 extends DrawerThemeData {
// Token database version: v0_150

class _DrawerDefaultsM3 extends DrawerThemeData {
const _DrawerDefaultsM3(this.context)
_DrawerDefaultsM3(this.context)
: super(elevation: 1.0);

final BuildContext context;
late final TextDirection direction = Directionality.of(context);

@override
Color? get backgroundColor => Theme.of(context).colorScheme.surface;
Expand All @@ -844,18 +845,22 @@ class _DrawerDefaultsM3 extends DrawerThemeData {
@override
Color? get shadowColor => Colors.transparent;

// This don't appear to be tokens for this value, but it is
// shown in the spec.
// There isn't currently a token for this value, but it is shown in the spec,
// so hard coding here for now.
@override
ShapeBorder? get shape => const RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(right: Radius.circular(16.0)),
ShapeBorder? get shape => RoundedRectangleBorder(
borderRadius: const BorderRadiusDirectional.horizontal(
end: Radius.circular(16.0),
).resolve(direction),
);

// This don't appear to be tokens for this value, but it is
// shown in the spec.
// There isn't currently a token for this value, but it is shown in the spec,
// so hard coding here for now.
@override
ShapeBorder? get endShape => const RoundedRectangleBorder(
borderRadius: BorderRadius.horizontal(left: Radius.circular(16.0)),
ShapeBorder? get endShape => RoundedRectangleBorder(
borderRadius: const BorderRadiusDirectional.horizontal(
start: Radius.circular(16.0),
).resolve(direction),
);
}

Expand Down
166 changes: 166 additions & 0 deletions packages/flutter/test/material/drawer_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -567,4 +567,170 @@ void main() {
final RenderBox box = tester.renderObject(find.byType(Drawer));
expect(box.size.width, equals(smallWidth));
});

testWidgets('Drawer default shape (ltr)', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Directionality(
textDirection: TextDirection.ltr,
child: Scaffold(
drawer: Drawer(),
endDrawer: Drawer(),
),
),
),
);

final Finder drawerMaterial = find.descendant(
of: find.byType(Drawer),
matching: find.byType(Material),
);

final ScaffoldState state = tester.firstState(find.byType(Scaffold));

// Open the drawer.
state.openDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the drawer shape.
Material material = tester.widget<Material>(drawerMaterial);
expect(
material.shape,
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.0),
bottomRight: Radius.circular(16.0),
),
),
);

// Close the opened drawer.
await tester.tapAt(const Offset(750, 300));
await tester.pumpAndSettle();

// Open the end drawer.
state.openEndDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the end drawer shape.
material = tester.widget<Material>(drawerMaterial);
expect(
material.shape,
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
bottomLeft: Radius.circular(16.0),
),
),
);
});

testWidgets('Drawer default shape (rtl)', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: true),
home: const Directionality(
textDirection: TextDirection.rtl,
child: Scaffold(
drawer: Drawer(),
endDrawer: Drawer(),
),
),
),
);

final Finder drawerMaterial = find.descendant(
of: find.byType(Drawer),
matching: find.byType(Material),
);

final ScaffoldState state = tester.firstState(find.byType(Scaffold));

// Open the drawer.
state.openDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the drawer shape.
Material material = tester.widget<Material>(drawerMaterial);
expect(
material.shape,
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16.0),
bottomLeft: Radius.circular(16.0),
),
),
);

// Close the opened drawer.
await tester.tapAt(const Offset(750, 300));
await tester.pumpAndSettle();

// Open the end drawer.
state.openEndDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the end drawer shape.
material = tester.widget<Material>(drawerMaterial);
expect(
material.shape,
const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topRight: Radius.circular(16.0),
bottomRight: Radius.circular(16.0),
),
),
);
});

group('Material 2', () {
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
// is turned on by default, these tests can be removed.

testWidgets('Drawer default shape', (WidgetTester tester) async {
await tester.pumpWidget(
MaterialApp(
theme: ThemeData(useMaterial3: false),
home: const Scaffold(
drawer: Drawer(),
endDrawer: Drawer(),
),
),
);

final Finder drawerMaterial = find.descendant(
of: find.byType(Drawer),
matching: find.byType(Material),
);

final ScaffoldState state = tester.firstState(find.byType(Scaffold));

// Open the drawer.
state.openDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the drawer shape.
Material material = tester.widget<Material>(drawerMaterial);
expect(material.shape, null);

// Close the opened drawer.
await tester.tapAt(const Offset(750, 300));
await tester.pumpAndSettle();

// Open the end drawer.
state.openEndDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));

// Test the end drawer shape.
material = tester.widget<Material>(drawerMaterial);
expect(material.shape, null);
});
});
}

0 comments on commit 0d91c03

Please sign in to comment.