import 'package:flutter/material.dart'; void showAppointmentBottomSheet( BuildContext context, { required Widget Function(BuildContext context) header, required SliverChildListDelegate Function(BuildContext context) body, }) { showModalBottomSheet( context: context, isScrollControlled: true, useSafeArea: true, backgroundColor: Theme.of(context).colorScheme.surface, builder: (sheetContext) => DraggableScrollableSheet( expand: false, initialChildSize: 0.4, minChildSize: 0.2, maxChildSize: 0.7, snap: true, snapSizes: const [0.4], builder: (_, scrollController) => CustomScrollView( controller: scrollController, slivers: [ SliverPersistentHeader( pinned: true, delegate: _StickyHeader(child: header(sheetContext)), ), SliverList(delegate: body(sheetContext)), ], ), ), ); } class _StickyHeader extends SliverPersistentHeaderDelegate { _StickyHeader({required this.child}); final Widget child; @override double get minExtent => 100; @override double get maxExtent => 100; @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => Material( color: Theme.of(context).colorScheme.surface, child: SizedBox.expand(child: child), ); @override bool shouldRebuild(covariant _StickyHeader oldDelegate) => oldDelegate.child != child; }