import 'package:flutter/material.dart'; import 'package:forui/forui.dart'; import '../constants/breakpoints.dart'; import '../theme/app_theme_scope.dart'; Future showAdaptiveModal({ required BuildContext context, required WidgetBuilder builder, double maxWidth = 520, double? maxHeight, double compactMaxHeightFactor = 0.92, double? compactHeightFactor, bool barrierDismissible = true, bool useRootNavigator = false, }) { final isCompact = Breakpoints.isCompact(MediaQuery.sizeOf(context).width); if (isCompact) { return showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, useRootNavigator: useRootNavigator, isDismissible: barrierDismissible, showDragHandle: true, backgroundColor: Colors.transparent, barrierColor: Colors.black54, builder: (sheetContext) => AppThemeScope( child: _AdaptiveBottomSheet( maxHeightFactor: compactMaxHeightFactor, heightFactor: compactHeightFactor, child: builder(sheetContext), ), ), ); } const insetPadding = EdgeInsets.symmetric(horizontal: 40, vertical: 32); return showFDialog( context: context, useRootNavigator: useRootNavigator, barrierDismissible: barrierDismissible, builder: (dialogContext, _, animation) { final screenHeight = MediaQuery.sizeOf(dialogContext).height; return AppThemeScope( child: FDialog.raw( animation: animation, clipBehavior: Clip.antiAlias, constraints: BoxConstraints( maxWidth: maxWidth, maxHeight: maxHeight ?? screenHeight - insetPadding.vertical, ), builder: (_, _) => builder(dialogContext), ), ); }, ); } class _AdaptiveBottomSheet extends StatelessWidget { final Widget child; final double maxHeightFactor; final double? heightFactor; const _AdaptiveBottomSheet({ required this.child, required this.maxHeightFactor, required this.heightFactor, }); @override Widget build(BuildContext context) { final theme = Theme.of(context); final size = MediaQuery.sizeOf(context); final viewInsets = MediaQuery.viewInsetsOf(context); final fixedHeight = heightFactor == null ? null : size.height * heightFactor!; final maxHeight = size.height * maxHeightFactor; Widget sheet = Material( color: theme.colorScheme.surface, clipBehavior: Clip.antiAlias, borderRadius: const BorderRadius.vertical(top: Radius.circular(24)), child: SafeArea( top: false, child: Column( mainAxisSize: fixedHeight == null ? MainAxisSize.min : MainAxisSize.max, children: [ if (fixedHeight == null) Flexible(fit: FlexFit.loose, child: child) else Expanded(child: child), ], ), ), ); sheet = ConstrainedBox( constraints: BoxConstraints(maxHeight: maxHeight), child: fixedHeight == null ? sheet : SizedBox(height: fixedHeight, child: sheet), ); return AnimatedPadding( duration: const Duration(milliseconds: 220), curve: Curves.easeOutCubic, padding: EdgeInsets.only(bottom: viewInsets.bottom), child: Align(alignment: Alignment.bottomCenter, child: sheet), ); } }