diff --git a/packages/flutter_adaptive_scaffold/CHANGELOG.md b/packages/flutter_adaptive_scaffold/CHANGELOG.md index 9646801d5336..90d1fc95556f 100644 --- a/packages/flutter_adaptive_scaffold/CHANGELOG.md +++ b/packages/flutter_adaptive_scaffold/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.2.3 + +* Update the spacing and margins to the latest material m3 specs. +* Add `margin`, `spacing`, `padding`, `recommendedPanes` and `maxPanes` with their Material value to `Breakpoint`. + ## 0.2.2 * Fix a bug where landscape would not show body when using `andUp`. diff --git a/packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart b/packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart index fc8db67bb046..3454192037ed 100644 --- a/packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart +++ b/packages/flutter_adaptive_scaffold/lib/src/adaptive_scaffold.dart @@ -8,21 +8,25 @@ import 'adaptive_layout.dart'; import 'breakpoints.dart'; import 'slot_layout.dart'; -/// Gutter value between different parts of the body slot depending on -/// material 3 design spec. -const double kMaterialGutterValue = 8; +/// Spacing value of the compact breakpoint according to +/// the material 3 design spec. +const double kMaterialCompactSpacing = 0; -/// Margin value of the compact breakpoint layout according to the material +/// Spacing value of the medium and up breakpoint according to +/// the material 3 design spec. +const double kMaterialMediumAndUpSpacing = 24; + +/// Margin value of the compact breakpoint according to the material /// design 3 spec. -const double kMaterialCompactMinMargin = 8; +const double kMaterialCompactMargin = 16; -/// Margin value of the medium breakpoint layout according to the material +/// Margin value of the medium breakpoint according to the material /// design 3 spec. -const double kMaterialMediumMinMargin = 12; +const double kMaterialMediumAndUpMargin = 24; -//// Margin value of the expanded breakpoint layout according to the material +/// Padding value of the compact breakpoint according to the material /// design 3 spec. -const double kMaterialExpandedMinMargin = 32; +const double kMaterialPadding = 4; /// Signature for a builder used by [AdaptiveScaffold.navigationRailDestinationBuilder] that converts a /// [NavigationDestination] to a [NavigationRailDestination]. @@ -429,40 +433,19 @@ class AdaptiveScaffold extends StatefulWidget { /// Public helper method to be used for creating a staggered grid following m3 /// specs from a list of [Widget]s static Builder toMaterialGrid({ - List thisWidgets = const [], - List breakpoints = const [ - Breakpoints.small, - Breakpoints.medium, - Breakpoints.mediumLarge, - Breakpoints.large, - Breakpoints.extraLarge, - ], - double margin = 8, - int itemColumns = 1, - required BuildContext context, + List widgets = const [], + List breakpoints = Breakpoints.all, + double? margin, + int? itemColumns, }) { return Builder(builder: (BuildContext context) { - Breakpoint? currentBreakpoint; - for (final Breakpoint breakpoint in breakpoints) { - if (breakpoint.isActive(context)) { - currentBreakpoint = breakpoint; - } - } - double? thisMargin = margin; + final Breakpoint? currentBreakpoint = + Breakpoint.activeBreakpointIn(context, breakpoints); + final double thisMargin = + margin ?? currentBreakpoint?.margin ?? kMaterialCompactMargin; + final int thisColumns = + itemColumns ?? currentBreakpoint?.recommendedPanes ?? 1; - if (currentBreakpoint == Breakpoints.small) { - if (thisMargin < kMaterialCompactMinMargin) { - thisMargin = kMaterialCompactMinMargin; - } - } else if (currentBreakpoint == Breakpoints.medium) { - if (thisMargin < kMaterialMediumMinMargin) { - thisMargin = kMaterialMediumMinMargin; - } - } else if (currentBreakpoint == Breakpoints.mediumLarge) { - if (thisMargin < kMaterialExpandedMinMargin) { - thisMargin = kMaterialExpandedMinMargin; - } - } return CustomScrollView( primary: false, controller: ScrollController(), @@ -473,11 +456,10 @@ class AdaptiveScaffold extends StatefulWidget { child: Padding( padding: EdgeInsets.all(thisMargin), child: _BrickLayout( - columns: itemColumns, - columnSpacing: kMaterialGutterValue, - itemPadding: - const EdgeInsets.only(bottom: kMaterialGutterValue), - children: thisWidgets, + columns: thisColumns, + columnSpacing: thisMargin, + itemPadding: EdgeInsets.only(bottom: thisMargin), + children: widgets, ), ), ), diff --git a/packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart b/packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart index c752222746f8..0ca452a8098b 100644 --- a/packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart +++ b/packages/flutter_adaptive_scaffold/lib/src/breakpoints.dart @@ -139,6 +139,11 @@ class Breakpoint { this.endHeight, this.andUp = false, this.platform, + this.spacing = kMaterialMediumAndUpSpacing, + this.margin = kMaterialMediumAndUpMargin, + this.padding = kMaterialPadding, + this.recommendedPanes = 1, + this.maxPanes = 1, }); /// Returns a [Breakpoint] that can be used as a fallthrough in the @@ -148,6 +153,11 @@ class Breakpoint { endWidth = null, beginHeight = null, endHeight = null, + spacing = kMaterialMediumAndUpSpacing, + margin = kMaterialMediumAndUpMargin, + padding = kMaterialPadding, + recommendedPanes = 1, + maxPanes = 1, andUp = true; /// Returns a [Breakpoint] with the given constraints for a small screen. @@ -155,35 +165,60 @@ class Breakpoint { : beginWidth = 0, endWidth = 600, beginHeight = null, - endHeight = 480; + endHeight = 480, + spacing = kMaterialCompactSpacing, + margin = kMaterialCompactMargin, + padding = kMaterialPadding, + recommendedPanes = 1, + maxPanes = 1; /// Returns a [Breakpoint] with the given constraints for a medium screen. const Breakpoint.medium({this.andUp = false, this.platform}) : beginWidth = 600, endWidth = 840, beginHeight = 480, - endHeight = 900; + endHeight = 900, + spacing = kMaterialMediumAndUpSpacing, + margin = kMaterialMediumAndUpMargin, + padding = kMaterialPadding * 2, + recommendedPanes = 1, + maxPanes = 2; /// Returns a [Breakpoint] with the given constraints for a mediumLarge screen. const Breakpoint.mediumLarge({this.andUp = false, this.platform}) : beginWidth = 840, endWidth = 1200, beginHeight = 900, - endHeight = null; + endHeight = null, + spacing = kMaterialMediumAndUpSpacing, + margin = kMaterialMediumAndUpMargin, + padding = kMaterialPadding * 3, + recommendedPanes = 2, + maxPanes = 2; /// Returns a [Breakpoint] with the given constraints for a large screen. const Breakpoint.large({this.andUp = false, this.platform}) : beginWidth = 1200, endWidth = 1600, beginHeight = 900, - endHeight = null; + endHeight = null, + spacing = kMaterialMediumAndUpSpacing, + margin = kMaterialMediumAndUpMargin, + padding = kMaterialPadding * 4, + recommendedPanes = 2, + maxPanes = 2; /// Returns a [Breakpoint] with the given constraints for an extraLarge screen. const Breakpoint.extraLarge({this.andUp = false, this.platform}) : beginWidth = 1600, endWidth = null, beginHeight = 900, - endHeight = null; + endHeight = null, + spacing = kMaterialMediumAndUpSpacing, + margin = kMaterialMediumAndUpMargin, + padding = kMaterialPadding * 5, + recommendedPanes = 2, + maxPanes = 3; /// A set of [TargetPlatform]s that the [Breakpoint] will be active on desktop. static const Set desktop = { @@ -222,6 +257,21 @@ class Breakpoint { /// left null then it will be active on all platforms. final Set? platform; + /// The default material spacing for the [Breakpoint]. + final double spacing; + + /// The default material margin for the [Breakpoint]. + final double margin; + + /// The default material padding for the [Breakpoint]. + final double padding; + + /// The material recommended number of panes for the [Breakpoint]. + final int recommendedPanes; + + /// The material maximum number of panes that can be displayed on the [Breakpoint]. + final int maxPanes; + /// A method that returns true based on conditions related to the context of /// the screen such as MediaQuery.sizeOf(context).width, MediaQuery.sizeOf(context).height /// and MediaQuery.orientationOf(context). diff --git a/packages/flutter_adaptive_scaffold/pubspec.yaml b/packages/flutter_adaptive_scaffold/pubspec.yaml index ad18e0cf9cc9..5800621d2b03 100644 --- a/packages/flutter_adaptive_scaffold/pubspec.yaml +++ b/packages/flutter_adaptive_scaffold/pubspec.yaml @@ -1,6 +1,6 @@ name: flutter_adaptive_scaffold description: Widgets to easily build adaptive layouts, including navigation elements. -version: 0.2.2 +version: 0.2.3 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+flutter_adaptive_scaffold%22 repository: https://github.com/flutter/packages/tree/main/packages/flutter_adaptive_scaffold diff --git a/packages/flutter_adaptive_scaffold/test/adaptive_scaffold_test.dart b/packages/flutter_adaptive_scaffold/test/adaptive_scaffold_test.dart index 45afcddce871..b7864392d690 100644 --- a/packages/flutter_adaptive_scaffold/test/adaptive_scaffold_test.dart +++ b/packages/flutter_adaptive_scaffold/test/adaptive_scaffold_test.dart @@ -31,7 +31,7 @@ void main() { final Finder primaryNav3 = find.byKey(const Key('primaryNavigation3')); await tester.binding.setSurfaceSize(SimulatedLayout.small.size); - await tester.pumpWidget(SimulatedLayout.small.app()); + await tester.pumpWidget(SimulatedLayout.small.scaffold(tester)); await tester.pumpAndSettle(); expect(smallBody, findsOneWidget); @@ -44,7 +44,7 @@ void main() { expect(tester.getTopLeft(bottomNav), const Offset(0, 1920)); await tester.binding.setSurfaceSize(SimulatedLayout.medium.size); - await tester.pumpWidget(SimulatedLayout.medium.app()); + await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester)); await tester.pumpAndSettle(); expect(smallBody, findsNothing); @@ -60,7 +60,7 @@ void main() { expect(tester.getBottomRight(primaryNav), const Offset(88, 2000)); await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size); - await tester.pumpWidget(SimulatedLayout.mediumLarge.app()); + await tester.pumpWidget(SimulatedLayout.mediumLarge.scaffold(tester)); await tester.pumpAndSettle(); expect(body, findsNothing); @@ -76,7 +76,7 @@ void main() { expect(tester.getBottomRight(primaryNav1), const Offset(208, 2000)); await tester.binding.setSurfaceSize(SimulatedLayout.large.size); - await tester.pumpWidget(SimulatedLayout.large.app()); + await tester.pumpWidget(SimulatedLayout.large.scaffold(tester)); await tester.pumpAndSettle(); expect(mediumLargeBody, findsNothing); @@ -92,7 +92,7 @@ void main() { expect(tester.getBottomRight(primaryNav2), const Offset(208, 2000)); await tester.binding.setSurfaceSize(SimulatedLayout.extraLarge.size); - await tester.pumpWidget(SimulatedLayout.extraLarge.app()); + await tester.pumpWidget(SimulatedLayout.extraLarge.scaffold(tester)); await tester.pumpAndSettle(); expect(largeBody, findsNothing); @@ -114,9 +114,9 @@ void main() { final Finder sBody = find.byKey(const Key('sBody')); await tester.binding.setSurfaceSize(SimulatedLayout.small.size); - await tester.pumpWidget(SimulatedLayout.small.app()); + await tester.pumpWidget(SimulatedLayout.small.scaffold(tester)); await tester.binding.setSurfaceSize(SimulatedLayout.medium.size); - await tester.pumpWidget(SimulatedLayout.medium.app()); + await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester)); await tester.pump(); await tester.pump(const Duration(milliseconds: 200)); @@ -155,10 +155,12 @@ void main() { final Finder sBody = find.byKey(const Key('sBody')); await tester.binding.setSurfaceSize(SimulatedLayout.small.size); - await tester.pumpWidget(SimulatedLayout.small.app(animations: false)); + await tester + .pumpWidget(SimulatedLayout.small.scaffold(tester, animations: false)); await tester.binding.setSurfaceSize(SimulatedLayout.medium.size); - await tester.pumpWidget(SimulatedLayout.medium.app(animations: false)); + await tester + .pumpWidget(SimulatedLayout.medium.scaffold(tester, animations: false)); await tester.pump(); await tester.pump(const Duration(milliseconds: 200)); @@ -179,7 +181,8 @@ void main() { await Future.forEach(SimulatedLayout.values, (SimulatedLayout region) async { int selectedIndex = 0; - final MaterialApp app = region.app(initialIndex: selectedIndex); + final MaterialApp app = + region.scaffold(tester, initialIndex: selectedIndex); await tester.binding.setSurfaceSize(region.size); await tester.pumpWidget(app); await tester.pumpAndSettle(); @@ -242,7 +245,7 @@ void main() { (WidgetTester tester) async { await Future.forEach(SimulatedLayout.values, (SimulatedLayout region) async { - final MaterialApp app = region.app(); + final MaterialApp app = region.scaffold(tester); await tester.binding.setSurfaceSize(region.size); await tester.pumpWidget(app); await tester.pumpAndSettle(); @@ -272,7 +275,8 @@ void main() { await Future.forEach(SimulatedLayout.values, (SimulatedLayout region) async { int? selectedIndex; - final MaterialApp app = region.app(initialIndex: selectedIndex); + final MaterialApp app = + region.scaffold(tester, initialIndex: selectedIndex); await tester.binding.setSurfaceSize(region.size); await tester.pumpWidget(app); await tester.pumpAndSettle(); @@ -453,7 +457,7 @@ void main() { 'when view in medium screen, navigation rail must be visible as per theme data values.', (WidgetTester tester) async { await tester.binding.setSurfaceSize(SimulatedLayout.medium.size); - await tester.pumpWidget(SimulatedLayout.medium.app()); + await tester.pumpWidget(SimulatedLayout.medium.scaffold(tester)); await tester.pumpAndSettle(); final Finder primaryNavigationMedium = find.byKey( @@ -499,7 +503,7 @@ void main() { 'when view in mediumLarge screen, navigation rail must be visible as per theme data values.', (WidgetTester tester) async { await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size); - await tester.pumpWidget(SimulatedLayout.mediumLarge.app()); + await tester.pumpWidget(SimulatedLayout.mediumLarge.scaffold(tester)); await tester.pumpAndSettle(); final Finder primaryNavigationMediumLarge = find.byKey( @@ -740,7 +744,7 @@ void main() { (WidgetTester tester) async { await tester.binding.setSurfaceSize(SimulatedLayout.medium.size); await tester.pumpWidget(SimulatedLayout.medium - .app(appBarBreakpoint: AppBarAlwaysOnBreakpoint())); + .scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint())); await tester.pumpAndSettle(); final Finder appBar = find.byType(AppBar); @@ -750,7 +754,7 @@ void main() { await tester.binding.setSurfaceSize(SimulatedLayout.mediumLarge.size); await tester.pumpWidget(SimulatedLayout.mediumLarge - .app(appBarBreakpoint: AppBarAlwaysOnBreakpoint())); + .scaffold(tester, appBarBreakpoint: AppBarAlwaysOnBreakpoint())); expect(drawer, findsNothing); await tester.pumpAndSettle(); diff --git a/packages/flutter_adaptive_scaffold/test/breakpoint_test.dart b/packages/flutter_adaptive_scaffold/test/breakpoint_test.dart index 88a8569136c6..61bcb5e643ed 100644 --- a/packages/flutter_adaptive_scaffold/test/breakpoint_test.dart +++ b/packages/flutter_adaptive_scaffold/test/breakpoint_test.dart @@ -3,7 +3,7 @@ // found in the LICENSE file. import 'package:flutter/material.dart'; -import 'package:flutter_adaptive_scaffold/src/breakpoints.dart'; +import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; import 'package:flutter_test/flutter_test.dart'; import 'simulated_layout.dart'; @@ -674,6 +674,291 @@ void main() { expect(find.byKey(const Key('Breakpoints.mediumAndUp')), findsOneWidget); }); }); + + // Test for `spacing`. + group('spacing property', () { + testWidgets('returns kMaterialCompactSpacing for small breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.small.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.smallMobile')))) + .spacing, + kMaterialCompactSpacing); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpSpacing for medium breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.medium.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.mediumMobile')))) + .spacing, + kMaterialMediumAndUpSpacing); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets( + 'returns kMaterialMediumAndUpSpacing for mediumLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.mediumLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.mediumLargeMobile')))) + .spacing, + kMaterialMediumAndUpSpacing); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpSpacing for large breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.large.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.largeMobile')))) + .spacing, + kMaterialMediumAndUpSpacing); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpSpacing for extraLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.extraLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.extraLargeMobile')))) + .spacing, + kMaterialMediumAndUpSpacing); + }, variant: TargetPlatformVariant.mobile()); + }); + + // Test for `margin`. + group('margin property', () { + testWidgets('returns kMaterialCompactMargin for small breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.small.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.smallMobile')))) + .margin, + kMaterialCompactMargin); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpMargin for medium breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.medium.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.mediumMobile')))) + .margin, + kMaterialMediumAndUpMargin); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpMargin for mediumLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.mediumLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.mediumLargeMobile')))) + .margin, + kMaterialMediumAndUpMargin); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpMargin for large breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.large.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.largeMobile')))) + .margin, + kMaterialMediumAndUpMargin); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialMediumAndUpMargin for extraLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.extraLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.extraLargeMobile')))) + .margin, + kMaterialMediumAndUpMargin); + }, variant: TargetPlatformVariant.mobile()); + }); + + // Test for `padding`. + group('padding property', () { + testWidgets('returns kMaterialPadding for small breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.small.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.smallMobile')))) + .padding, + kMaterialPadding); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialPadding * 2 for medium breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.medium.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.mediumMobile')))) + .padding, + kMaterialPadding * 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialPadding * 3 for mediumLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.mediumLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.mediumLargeMobile')))) + .padding, + kMaterialPadding * 3); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialPadding * 4 for large breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.large.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.largeMobile')))) + .padding, + kMaterialPadding * 4); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns kMaterialPadding * 5 for extraLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.extraLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.extraLargeMobile')))) + .padding, + kMaterialPadding * 5); + }, variant: TargetPlatformVariant.mobile()); + }); + + // Test for `recommendedPanes`. + group('recommendedPanes property', () { + testWidgets('returns 1 for small breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.small.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.smallMobile')))) + .recommendedPanes, + 1); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 1 for medium breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.medium.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.mediumMobile')))) + .recommendedPanes, + 1); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for mediumLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.mediumLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.mediumLargeMobile')))) + .recommendedPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for large breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.large.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.largeMobile')))) + .recommendedPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for extraLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.extraLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.extraLargeMobile')))) + .recommendedPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + }); + + // Test for `maxPanes`. + group('maxPanes property', () { + testWidgets('returns 1 for small breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.small.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.smallMobile')))) + .maxPanes, + 1); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for medium breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.medium.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.mediumMobile')))) + .maxPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for mediumLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.mediumLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.mediumLargeMobile')))) + .maxPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 2 for large breakpoint', (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.large.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester + .element(find.byKey(const Key('Breakpoints.largeMobile')))) + .maxPanes, + 2); + }, variant: TargetPlatformVariant.mobile()); + + testWidgets('returns 3 for extraLarge breakpoint', + (WidgetTester tester) async { + await tester.pumpWidget(SimulatedLayout.extraLarge.slot(tester)); + await tester.pumpAndSettle(); + expect( + Breakpoint.activeBreakpointOf(tester.element( + find.byKey(const Key('Breakpoints.extraLargeMobile')))) + .maxPanes, + 3); + }, variant: TargetPlatformVariant.mobile()); + }); } class DummyWidget extends StatelessWidget { diff --git a/packages/flutter_adaptive_scaffold/test/simulated_layout.dart b/packages/flutter_adaptive_scaffold/test/simulated_layout.dart index a72014192283..afa5e1a311c1 100644 --- a/packages/flutter_adaptive_scaffold/test/simulated_layout.dart +++ b/packages/flutter_adaptive_scaffold/test/simulated_layout.dart @@ -148,11 +148,7 @@ enum SimulatedLayout { Size get size => Size(_width, _height); - MaterialApp app({ - int? initialIndex, - bool animations = true, - Breakpoint? appBarBreakpoint, - }) { + MaterialApp app(WidgetTester tester, {required Widget child}) { return MaterialApp( theme: ThemeData.light().copyWith( navigationRailTheme: const NavigationRailThemeData( @@ -162,15 +158,27 @@ enum SimulatedLayout { ), ), home: MediaQuery( - data: MediaQueryData( - size: size, + data: MediaQueryData.fromView(tester.view).copyWith( + size: Size(_width, _height), padding: const EdgeInsets.only(top: 30), ), - child: TestScaffold( - initialIndex: initialIndex, - isAnimated: animations, - appBarBreakpoint: appBarBreakpoint, - ), + child: child, + ), + ); + } + + MaterialApp scaffold( + WidgetTester tester, { + int? initialIndex, + bool animations = true, + Breakpoint? appBarBreakpoint, + }) { + return app( + tester, + child: TestScaffold( + initialIndex: initialIndex, + isAnimated: animations, + appBarBreakpoint: appBarBreakpoint, ), ); }