Skip to content

Commit 0d91c03

Browse files
authored
Fix M3 Drawer default shape in RTL (flutter#118185)
1 parent 51c2af5 commit 0d91c03

File tree

3 files changed

+194
-18
lines changed

3 files changed

+194
-18
lines changed

Diff for: dev/tools/gen_defaults/lib/drawer_template.dart

+14-9
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ class DrawerTemplate extends TokenTemplate {
1010
@override
1111
String generate() => '''
1212
class _${blockName}DefaultsM3 extends DrawerThemeData {
13-
const _${blockName}DefaultsM3(this.context)
13+
_${blockName}DefaultsM3(this.context)
1414
: super(elevation: ${elevation("md.comp.navigation-drawer.modal.container")});
1515
1616
final BuildContext context;
17+
late final TextDirection direction = Directionality.of(context);
1718
1819
@override
1920
Color? get backgroundColor => ${componentColor("md.comp.navigation-drawer.container")};
@@ -24,18 +25,22 @@ class _${blockName}DefaultsM3 extends DrawerThemeData {
2425
@override
2526
Color? get shadowColor => ${colorOrTransparent("md.comp.navigation-drawer.container.shadow-color")};
2627
27-
// This don't appear to be tokens for this value, but it is
28-
// shown in the spec.
28+
// There isn't currently a token for this value, but it is shown in the spec,
29+
// so hard coding here for now.
2930
@override
30-
ShapeBorder? get shape => const RoundedRectangleBorder(
31-
borderRadius: BorderRadius.horizontal(right: Radius.circular(16.0)),
31+
ShapeBorder? get shape => RoundedRectangleBorder(
32+
borderRadius: const BorderRadiusDirectional.horizontal(
33+
end: Radius.circular(16.0),
34+
).resolve(direction),
3235
);
3336
34-
// This don't appear to be tokens for this value, but it is
35-
// shown in the spec.
37+
// There isn't currently a token for this value, but it is shown in the spec,
38+
// so hard coding here for now.
3639
@override
37-
ShapeBorder? get endShape => const RoundedRectangleBorder(
38-
borderRadius: BorderRadius.horizontal(left: Radius.circular(16.0)),
40+
ShapeBorder? get endShape => RoundedRectangleBorder(
41+
borderRadius: const BorderRadiusDirectional.horizontal(
42+
start: Radius.circular(16.0),
43+
).resolve(direction),
3944
);
4045
}
4146
''';

Diff for: packages/flutter/lib/src/material/drawer.dart

+14-9
Original file line numberDiff line numberDiff line change
@@ -830,10 +830,11 @@ class _DrawerDefaultsM2 extends DrawerThemeData {
830830
// Token database version: v0_150
831831

832832
class _DrawerDefaultsM3 extends DrawerThemeData {
833-
const _DrawerDefaultsM3(this.context)
833+
_DrawerDefaultsM3(this.context)
834834
: super(elevation: 1.0);
835835

836836
final BuildContext context;
837+
late final TextDirection direction = Directionality.of(context);
837838

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

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

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

Diff for: packages/flutter/test/material/drawer_test.dart

+166
Original file line numberDiff line numberDiff line change
@@ -567,4 +567,170 @@ void main() {
567567
final RenderBox box = tester.renderObject(find.byType(Drawer));
568568
expect(box.size.width, equals(smallWidth));
569569
});
570+
571+
testWidgets('Drawer default shape (ltr)', (WidgetTester tester) async {
572+
await tester.pumpWidget(
573+
MaterialApp(
574+
theme: ThemeData(useMaterial3: true),
575+
home: const Directionality(
576+
textDirection: TextDirection.ltr,
577+
child: Scaffold(
578+
drawer: Drawer(),
579+
endDrawer: Drawer(),
580+
),
581+
),
582+
),
583+
);
584+
585+
final Finder drawerMaterial = find.descendant(
586+
of: find.byType(Drawer),
587+
matching: find.byType(Material),
588+
);
589+
590+
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
591+
592+
// Open the drawer.
593+
state.openDrawer();
594+
await tester.pump();
595+
await tester.pump(const Duration(seconds: 1));
596+
597+
// Test the drawer shape.
598+
Material material = tester.widget<Material>(drawerMaterial);
599+
expect(
600+
material.shape,
601+
const RoundedRectangleBorder(
602+
borderRadius: BorderRadius.only(
603+
topRight: Radius.circular(16.0),
604+
bottomRight: Radius.circular(16.0),
605+
),
606+
),
607+
);
608+
609+
// Close the opened drawer.
610+
await tester.tapAt(const Offset(750, 300));
611+
await tester.pumpAndSettle();
612+
613+
// Open the end drawer.
614+
state.openEndDrawer();
615+
await tester.pump();
616+
await tester.pump(const Duration(seconds: 1));
617+
618+
// Test the end drawer shape.
619+
material = tester.widget<Material>(drawerMaterial);
620+
expect(
621+
material.shape,
622+
const RoundedRectangleBorder(
623+
borderRadius: BorderRadius.only(
624+
topLeft: Radius.circular(16.0),
625+
bottomLeft: Radius.circular(16.0),
626+
),
627+
),
628+
);
629+
});
630+
631+
testWidgets('Drawer default shape (rtl)', (WidgetTester tester) async {
632+
await tester.pumpWidget(
633+
MaterialApp(
634+
theme: ThemeData(useMaterial3: true),
635+
home: const Directionality(
636+
textDirection: TextDirection.rtl,
637+
child: Scaffold(
638+
drawer: Drawer(),
639+
endDrawer: Drawer(),
640+
),
641+
),
642+
),
643+
);
644+
645+
final Finder drawerMaterial = find.descendant(
646+
of: find.byType(Drawer),
647+
matching: find.byType(Material),
648+
);
649+
650+
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
651+
652+
// Open the drawer.
653+
state.openDrawer();
654+
await tester.pump();
655+
await tester.pump(const Duration(seconds: 1));
656+
657+
// Test the drawer shape.
658+
Material material = tester.widget<Material>(drawerMaterial);
659+
expect(
660+
material.shape,
661+
const RoundedRectangleBorder(
662+
borderRadius: BorderRadius.only(
663+
topLeft: Radius.circular(16.0),
664+
bottomLeft: Radius.circular(16.0),
665+
),
666+
),
667+
);
668+
669+
// Close the opened drawer.
670+
await tester.tapAt(const Offset(750, 300));
671+
await tester.pumpAndSettle();
672+
673+
// Open the end drawer.
674+
state.openEndDrawer();
675+
await tester.pump();
676+
await tester.pump(const Duration(seconds: 1));
677+
678+
// Test the end drawer shape.
679+
material = tester.widget<Material>(drawerMaterial);
680+
expect(
681+
material.shape,
682+
const RoundedRectangleBorder(
683+
borderRadius: BorderRadius.only(
684+
topRight: Radius.circular(16.0),
685+
bottomRight: Radius.circular(16.0),
686+
),
687+
),
688+
);
689+
});
690+
691+
group('Material 2', () {
692+
// Tests that are only relevant for Material 2. Once ThemeData.useMaterial3
693+
// is turned on by default, these tests can be removed.
694+
695+
testWidgets('Drawer default shape', (WidgetTester tester) async {
696+
await tester.pumpWidget(
697+
MaterialApp(
698+
theme: ThemeData(useMaterial3: false),
699+
home: const Scaffold(
700+
drawer: Drawer(),
701+
endDrawer: Drawer(),
702+
),
703+
),
704+
);
705+
706+
final Finder drawerMaterial = find.descendant(
707+
of: find.byType(Drawer),
708+
matching: find.byType(Material),
709+
);
710+
711+
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
712+
713+
// Open the drawer.
714+
state.openDrawer();
715+
await tester.pump();
716+
await tester.pump(const Duration(seconds: 1));
717+
718+
// Test the drawer shape.
719+
Material material = tester.widget<Material>(drawerMaterial);
720+
expect(material.shape, null);
721+
722+
// Close the opened drawer.
723+
await tester.tapAt(const Offset(750, 300));
724+
await tester.pumpAndSettle();
725+
726+
// Open the end drawer.
727+
state.openEndDrawer();
728+
await tester.pump();
729+
await tester.pump(const Duration(seconds: 1));
730+
731+
// Test the end drawer shape.
732+
material = tester.widget<Material>(drawerMaterial);
733+
expect(material.shape, null);
734+
});
735+
});
570736
}

0 commit comments

Comments
 (0)