diff --git a/.vscode/launch.json b/.vscode/launch.json index 4ff70b67..71aca65c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -25,6 +25,13 @@ "program": "lib/showcase/todo_list/main.dart", "cwd": "./cookbook" }, + { + "name": "Safari", + "request": "launch", + "type": "dart", + "program": "lib/showcase/safari/main.dart", + "cwd": "./cookbook" + }, { "name": "Scrollable Sheet", "request": "launch", @@ -95,6 +102,13 @@ "program": "lib/tutorial/imperative_modal_sheet.dart", "cwd": "./cookbook" }, + { + "name": "Cupertino Modal Sheet", + "request": "launch", + "type": "dart", + "program": "lib/tutorial/cupertino_modal_sheet.dart", + "cwd": "./cookbook" + }, { "name": "Extent Driven Animation", "request": "launch", diff --git a/cookbook/assets/apple_website.png b/cookbook/assets/apple_website.png new file mode 100644 index 00000000..ca13b8e0 Binary files /dev/null and b/cookbook/assets/apple_website.png differ diff --git a/cookbook/ios/Flutter/AppFrameworkInfo.plist b/cookbook/ios/Flutter/AppFrameworkInfo.plist index 9625e105..7c569640 100644 --- a/cookbook/ios/Flutter/AppFrameworkInfo.plist +++ b/cookbook/ios/Flutter/AppFrameworkInfo.plist @@ -21,6 +21,6 @@ CFBundleVersion 1.0 MinimumOSVersion - 11.0 + 12.0 diff --git a/cookbook/ios/Runner.xcodeproj/project.pbxproj b/cookbook/ios/Runner.xcodeproj/project.pbxproj index 64ea3e52..ed332670 100644 --- a/cookbook/ios/Runner.xcodeproj/project.pbxproj +++ b/cookbook/ios/Runner.xcodeproj/project.pbxproj @@ -345,7 +345,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -473,7 +473,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -522,7 +522,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 11.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; diff --git a/cookbook/lib/showcase/safari/actions.dart b/cookbook/lib/showcase/safari/actions.dart new file mode 100644 index 00000000..f4d63bb4 --- /dev/null +++ b/cookbook/lib/showcase/safari/actions.dart @@ -0,0 +1,132 @@ +import 'package:cookbook/showcase/safari/common.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +void showEditActionsSheet(BuildContext context) { + Navigator.push( + context, + CupertinoModalSheetRoute( + builder: (context) => const EditActionsSheet(), + ), + ); +} + +class EditActionsSheet extends StatelessWidget { + const EditActionsSheet({super.key}); + + @override + Widget build(BuildContext context) { + return ScrollableSheet( + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: SheetContentScaffold( + backgroundColor: CupertinoColors.systemGroupedBackground, + appBar: CupertinoAppBar( + title: const Text('Edit Actions'), + trailing: CupertinoButton( + onPressed: () => Navigator.pop(context), + child: const Text('Done'), + ), + ), + body: const _ActionList(), + ), + ), + ); + } +} + +class _ActionList extends StatelessWidget { + const _ActionList(); + + @override + Widget build(BuildContext context) { + return ListView( + children: const [ + SizedBox(height: 16), + _ActionListSection( + header: Text('Favorites'), + children: [ + _ActionListItem(title: 'Copy', isFavorite: true), + _ActionListItem(title: 'Save in Keep', isFavorite: true), + ], + ), + SizedBox(height: 16), + _ActionListSection( + header: Text('Safari'), + children: [ + _ActionListItem(title: 'Add to Reading List'), + _ActionListItem(title: 'Add Bookmark'), + _ActionListItem(title: 'Add to Favorites'), + _ActionListItem(title: 'Add to Quick Note'), + _ActionListItem(title: 'Find on Page'), + _ActionListItem(title: 'Add to Home Screen'), + ], + ), + SizedBox(height: 16), + _ActionListSection( + header: Text('Other actions'), + children: [ + _ActionListItem(title: 'Markup'), + _ActionListItem(title: 'Print'), + _ActionListItem(title: 'Analyze with Bing Chat'), + _ActionListItem(title: 'Open in Chrome'), + _ActionListItem(title: 'Open using Mastodon'), + _ActionListItem(title: 'Save to Pinterest'), + _ActionListItem(title: 'Save to Dropbox'), + ], + ), + ], + ); + } +} + +class _ActionListSection extends StatelessWidget { + const _ActionListSection({ + this.header, + required this.children, + }); + + final Widget? header; + final List children; + + @override + Widget build(BuildContext context) { + return CupertinoListSection.insetGrouped( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + header: header, + children: children, + ); + } +} + +class _ActionListItem extends StatelessWidget { + const _ActionListItem({ + required this.title, + this.isFavorite = false, + }); + + final String title; + final bool isFavorite; + + @override + Widget build(BuildContext context) { + return CupertinoListTile.notched( + title: Text(title), + leading: isFavorite + ? const Icon( + CupertinoIcons.minus_circle_fill, + color: CupertinoColors.systemRed, + ) + : const Icon( + CupertinoIcons.plus_circle_fill, + color: CupertinoColors.systemGreen, + ), + trailing: isFavorite + ? const Icon( + CupertinoIcons.line_horizontal_3, + color: CupertinoColors.systemGrey4, + ) + : null, + ); + } +} diff --git a/cookbook/lib/showcase/safari/bookmark.dart b/cookbook/lib/showcase/safari/bookmark.dart new file mode 100644 index 00000000..3102eb8d --- /dev/null +++ b/cookbook/lib/showcase/safari/bookmark.dart @@ -0,0 +1,105 @@ +import 'package:cookbook/showcase/safari/common.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +void showEditBookmarkSheet(BuildContext context) { + Navigator.push( + context, + CupertinoModalSheetRoute( + builder: (context) => const EditBookmarkSheet( + pageUrl: 'https://www.apple.com', + faviconUrl: 'https://www.apple.com/favicon.ico', + ), + ), + ); +} + +class EditBookmarkSheet extends StatelessWidget { + const EditBookmarkSheet({ + super.key, + required this.pageUrl, + required this.faviconUrl, + }); + + final String pageUrl; + final String faviconUrl; + + @override + Widget build(BuildContext context) { + return DraggableSheet( + keyboardDismissBehavior: const SheetKeyboardDismissBehavior.onDragDown(), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: SheetContentScaffold( + backgroundColor: CupertinoColors.systemGroupedBackground, + appBar: CupertinoAppBar( + title: const Text('Add Bookmark'), + leading: CupertinoButton( + onPressed: () => Navigator.pop(context), + child: const Text('Cancel'), + ), + trailing: CupertinoButton( + onPressed: () => + Navigator.popUntil(context, (route) => route.isFirst), + child: const Text('Save'), + ), + ), + body: SizedBox.expand( + child: CupertinoListSection.insetGrouped( + children: [ + _BookmarkEditor( + pageUrl: pageUrl, + faviconUrl: faviconUrl, + ), + ], + ), + ), + ), + ), + ); + } +} + +class _BookmarkEditor extends StatelessWidget { + const _BookmarkEditor({ + required this.pageUrl, + required this.faviconUrl, + }); + + final String pageUrl; + final String faviconUrl; + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Padding( + padding: const EdgeInsets.all(16), + child: SiteIcon(url: faviconUrl), + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const CupertinoTextField.borderless( + padding: EdgeInsets.zero, + autofocus: true, + ), + const Divider(color: CupertinoColors.systemGrey5), + Text( + pageUrl, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: CupertinoColors.secondaryLabel), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ); + } +} diff --git a/cookbook/lib/showcase/safari/common.dart b/cookbook/lib/showcase/safari/common.dart new file mode 100644 index 00000000..6b1a8fed --- /dev/null +++ b/cookbook/lib/showcase/safari/common.dart @@ -0,0 +1,65 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; + +class CupertinoAppBar extends StatelessWidget implements PreferredSizeWidget { + const CupertinoAppBar({ + super.key, + required this.title, + this.leading, + this.trailing, + }); + + final Widget title; + final Widget? leading; + final Widget? trailing; + + @override + Size get preferredSize => const Size.fromHeight(56); + + @override + Widget build(BuildContext context) { + return Container( + height: preferredSize.height, + decoration: const BoxDecoration( + color: CupertinoColors.systemGroupedBackground, + border: Border(bottom: BorderSide(color: CupertinoColors.systemGrey5)), + ), + child: Stack( + alignment: Alignment.center, + children: [ + if (leading case final leading?) + Positioned( + left: 1, + child: leading, + ), + DefaultTextStyle( + style: Theme.of(context).textTheme.titleMedium!, + child: title, + ), + if (trailing case final trailing?) + Positioned( + right: 1, + child: trailing, + ), + ], + ), + ); + } +} + +class SiteIcon extends StatelessWidget { + const SiteIcon({ + super.key, + required this.url, + }); + + final String url; + + @override + Widget build(BuildContext context) { + return SizedBox.square( + dimension: 48, + child: Image.network(url), + ); + } +} diff --git a/cookbook/lib/showcase/safari/home.dart b/cookbook/lib/showcase/safari/home.dart new file mode 100644 index 00000000..87de9c27 --- /dev/null +++ b/cookbook/lib/showcase/safari/home.dart @@ -0,0 +1,135 @@ +import 'package:cookbook/showcase/safari/menu.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +class Home extends StatelessWidget { + const Home({super.key}); + + @override + Widget build(BuildContext context) { + return CupertinoStackedTransition( + cornerRadius: Tween(begin: 0.0, end: 16.0), + child: CupertinoPageScaffold( + child: SafeArea( + bottom: false, + child: Column( + children: [ + Expanded( + child: SingleChildScrollView( + child: Image.asset( + 'assets/apple_website.png', + fit: BoxFit.fitWidth, + ), + ), + ), + const _BottomBar(), + ], + ), + ), + ), + ); + } +} + +class _BottomBar extends StatelessWidget { + const _BottomBar(); + + @override + Widget build(BuildContext context) { + return const ColoredBox( + color: CupertinoColors.systemGroupedBackground, + child: SafeArea( + child: Column( + children: [ + Divider(height: 1, color: CupertinoColors.systemGrey5), + _AddressBar(), + _ToolBar(), + ], + ), + ), + ); + } +} + +class _AddressBar extends StatelessWidget { + const _AddressBar(); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.symmetric(horizontal: 24, vertical: 10), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: CupertinoColors.systemBackground, + borderRadius: BorderRadius.circular(12), + boxShadow: const [ + BoxShadow( + color: CupertinoColors.systemGrey5, + offset: Offset(0, 1), + blurRadius: 10, + ), + ], + ), + child: const Row( + children: [ + Icon( + CupertinoIcons.textformat, + color: CupertinoColors.black, + ), + Expanded( + child: Text( + 'apple.com', + textAlign: TextAlign.center, + ), + ), + Icon( + CupertinoIcons.refresh, + color: CupertinoColors.black, + ), + ], + ), + ); + } +} + +class _ToolBar extends StatelessWidget { + const _ToolBar(); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + CupertinoButton( + padding: EdgeInsets.zero, + onPressed: () {}, + child: const Icon(CupertinoIcons.left_chevron), + ), + const CupertinoButton( + padding: EdgeInsets.zero, + onPressed: null, + child: Icon(CupertinoIcons.right_chevron), + ), + CupertinoButton( + padding: EdgeInsets.zero, + onPressed: () => showMenuSheet(context), + child: const Icon(CupertinoIcons.share), + ), + CupertinoButton( + padding: EdgeInsets.zero, + onPressed: () {}, + child: const Icon(CupertinoIcons.book), + ), + CupertinoButton( + padding: EdgeInsets.zero, + onPressed: () {}, + child: const Icon(CupertinoIcons.square_on_square), + ), + ], + ), + ); + } +} diff --git a/cookbook/lib/showcase/safari/main.dart b/cookbook/lib/showcase/safari/main.dart new file mode 100644 index 00000000..1c93cd04 --- /dev/null +++ b/cookbook/lib/showcase/safari/main.dart @@ -0,0 +1,15 @@ +import 'package:cookbook/showcase/safari/home.dart'; +import 'package:flutter/cupertino.dart'; + +void main() { + runApp(const _SafariApp()); +} + +class _SafariApp extends StatelessWidget { + const _SafariApp(); + + @override + Widget build(BuildContext context) { + return const CupertinoApp(home: Home()); + } +} diff --git a/cookbook/lib/showcase/safari/menu.dart b/cookbook/lib/showcase/safari/menu.dart new file mode 100644 index 00000000..2a86dc01 --- /dev/null +++ b/cookbook/lib/showcase/safari/menu.dart @@ -0,0 +1,243 @@ +import 'package:cookbook/showcase/safari/actions.dart'; +import 'package:cookbook/showcase/safari/bookmark.dart'; +import 'package:cookbook/showcase/safari/common.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +void showMenuSheet(BuildContext context) { + Navigator.push( + context, + CupertinoModalSheetRoute( + builder: (context) => const MenuSheet(), + ), + ); +} + +class MenuSheet extends StatelessWidget { + const MenuSheet({super.key}); + + @override + Widget build(BuildContext context) { + const halfWayExtent = Extent.proportional(0.5); + return ScrollableSheet( + initialExtent: halfWayExtent, + minExtent: halfWayExtent, + physics: const StretchingSheetPhysics( + parent: SnappingSheetPhysics( + snappingBehavior: SnapToNearest( + snapTo: [halfWayExtent, Extent.proportional(1)], + ), + ), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(16), + child: const SheetContentScaffold( + backgroundColor: CupertinoColors.systemGroupedBackground, + body: Column( + children: [ + _TopBar( + pageTitle: 'Apple', + displayUrl: 'apple.com', + faviconUrl: 'https://www.apple.com/favicon.ico', + ), + Divider(height: 1, color: CupertinoColors.systemGrey5), + Expanded(child: _MenuList()), + ], + ), + ), + ), + ); + } +} + +class _MenuList extends StatelessWidget { + const _MenuList(); + + @override + Widget build(BuildContext context) { + return ListView( + padding: EdgeInsets.only( + top: 8, + bottom: MediaQuery.viewPaddingOf(context).bottom, + ), + children: [ + const _MenuListSection( + children: [ + _MenuListItem( + title: 'Copy', + icon: CupertinoIcons.doc_on_doc, + ), + _MenuListItem( + title: 'Save in Keep', + icon: CupertinoIcons.bookmark, + ), + ], + ), + const _MenuListSection( + children: [ + _MenuListItem( + title: 'Add to Reading List', + icon: CupertinoIcons.eyeglasses, + ), + _MenuListItem( + title: 'Add Bookmark', + icon: CupertinoIcons.book, + ), + _MenuListItem( + title: 'Add to Favorites', + icon: CupertinoIcons.star, + ), + _MenuListItem( + title: 'Find on Page', + icon: CupertinoIcons.doc_text_search, + ), + _MenuListItem( + title: 'Add to Home Screen', + icon: CupertinoIcons.add_circled, + ), + ], + ), + const _MenuListSection( + children: [ + _MenuListItem( + title: 'Markup', + icon: CupertinoIcons.pencil_outline, + ), + _MenuListItem( + title: 'Print', + icon: CupertinoIcons.printer, + ), + ], + ), + CupertinoListTile.notched( + title: CupertinoButton( + onPressed: () => showEditActionsSheet(context), + child: const Text('Edit Actions...'), + ), + ), + ], + ); + } +} + +class _MenuListSection extends StatelessWidget { + const _MenuListSection({ + required this.children, + }); + + final List children; + + @override + Widget build(BuildContext context) { + return CupertinoListSection.insetGrouped( + margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + children: children, + ); + } +} + +class _MenuListItem extends StatelessWidget { + const _MenuListItem({ + required this.title, + required this.icon, + }); + + final String title; + final IconData icon; + + @override + Widget build(BuildContext context) { + return CupertinoListTile.notched( + title: Text(title), + trailing: Icon(icon, color: CupertinoColors.black), + onTap: () { + DefaultSheetController.maybeOf(context) + ?.animateTo(const Extent.proportional(1)); + showEditBookmarkSheet(context); + }, + ); + } +} + +class _TopBar extends StatelessWidget { + const _TopBar({ + required this.pageTitle, + required this.displayUrl, + required this.faviconUrl, + }); + + final String pageTitle; + final String displayUrl; + final String faviconUrl; + + @override + Widget build(BuildContext context) { + final pageTitle = Text( + this.pageTitle, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.titleMedium, + ); + final displayUrl = Text( + this.displayUrl, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context) + .textTheme + .bodyMedium + ?.copyWith(color: CupertinoColors.secondaryLabel), + ); + + return SheetDraggable( + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 16, + vertical: 16, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SiteIcon(url: faviconUrl), + const SizedBox(width: 16), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [pageTitle, displayUrl], + ), + ), + const SizedBox(width: 16), + const _CloseButton(), + ], + ), + ), + ); + } +} + +class _CloseButton extends StatelessWidget { + const _CloseButton(); + + @override + Widget build(BuildContext context) { + return GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: () => Navigator.pop(context), + child: Container( + width: 36, + height: 36, + decoration: const ShapeDecoration( + shape: CircleBorder(), + color: CupertinoColors.systemGrey5, + ), + child: const Center( + child: Icon( + CupertinoIcons.xmark, + size: 18, + color: CupertinoColors.black, + ), + ), + ), + ); + } +} diff --git a/cookbook/lib/tutorial/cupertino_modal_sheet.dart b/cookbook/lib/tutorial/cupertino_modal_sheet.dart new file mode 100644 index 00000000..d63c82e1 --- /dev/null +++ b/cookbook/lib/tutorial/cupertino_modal_sheet.dart @@ -0,0 +1,137 @@ +import 'package:flutter/cupertino.dart'; +import 'package:smooth_sheets/smooth_sheets.dart'; + +void main() { + runApp(const _CupertinoModalSheetExample()); +} + +class _CupertinoModalSheetExample extends StatelessWidget { + const _CupertinoModalSheetExample(); + + @override + Widget build(BuildContext context) { + // Cupertino widgets are used in this example, + // but of course you can use material widgets as well. + return const CupertinoApp( + home: _ExampleHome(), + ); + } +} + +class _ExampleHome extends StatelessWidget { + const _ExampleHome(); + + @override + Widget build(BuildContext context) { + // It is recommended to wrap the top most non-modal page within a navigator + // with `CupertinoStackedTransition` to create more accurate ios 15 style + // transition animation; that is, while the first modal sheet goes to fullscreen, + // a non-modal page behind it will gradually reduce its size and the corner radius. + return CupertinoStackedTransition( + // The start and end values of the corner radius animation can be specified + // as the `cornerRadius` property. If `null` is specified (the default value), + // no corner radius animation is performed. + cornerRadius: Tween(begin: 0.0, end: 16.0), + child: CupertinoPageScaffold( + child: Center( + child: CupertinoButton.filled( + onPressed: () => _showModalSheet(context, isFullScreen: false), + child: const Text('Show Modal Sheet'), + ), + ), + ), + ); + } +} + +void _showModalSheet(BuildContext context, {required bool isFullScreen}) { + // Use `CupertinoModalSheetRoute` to show an ios 15 style modal sheet. + // For declarative navigation (Navigator 2.0), use `CupertinoModalSheetPage` instead. + final modalRoute = CupertinoModalSheetRoute( + builder: (context) => switch (isFullScreen) { + true => const _FullScreenSheet(), + false => const _HalfScreenSheet(), + }, + ); + + Navigator.push(context, modalRoute); +} + +class _HalfScreenSheet extends StatelessWidget { + const _HalfScreenSheet(); + + @override + Widget build(BuildContext context) { + // `CupertinoStackedTransition` won't start the transition animation until + // the visible height of a modal sheet (the extent) exceeds 50% of the screen height. + return const DraggableSheet( + initialExtent: Extent.proportional(0.5), + minExtent: Extent.proportional(0.5), + physics: StretchingSheetPhysics( + parent: SnappingSheetPhysics( + snappingBehavior: SnapToNearest( + snapTo: [ + Extent.proportional(0.5), + Extent.proportional(1), + ], + ), + ), + ), + child: _SheetContent(), + ); + } +} + +class _FullScreenSheet extends StatelessWidget { + const _FullScreenSheet(); + + @override + Widget build(BuildContext context) { + return const DraggableSheet( + child: _SheetContent(), + ); + } +} + +class _SheetContent extends StatelessWidget { + const _SheetContent(); + + @override + Widget build(BuildContext context) { + // Nothing special here, just a simple modal sheet content. + return DecoratedBox( + decoration: const ShapeDecoration( + color: CupertinoColors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all( + Radius.circular(16), + ), + ), + ), + child: SizedBox.expand( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + CupertinoButton.filled( + onPressed: () { + // `DefaultSheetController.of` is a handy way to obtain a `SheetController` + // that is exposed by the parent `CupertinoModalSheetRoute`. + DefaultSheetController.maybeOf(context) + ?.animateTo(const Extent.proportional(1)); + _showModalSheet(context, isFullScreen: true); + }, + child: const Text('Stack'), + ), + const SizedBox(height: 16), + CupertinoButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ), + ), + ), + ); + } +} diff --git a/cookbook/pubspec.yaml b/cookbook/pubspec.yaml index 82c475ec..4d2d5ca1 100644 --- a/cookbook/pubspec.yaml +++ b/cookbook/pubspec.yaml @@ -7,6 +7,7 @@ environment: dependencies: animations: ^2.0.10 + cupertino_icons: ^1.0.6 faker: ^2.1.0 flutter: sdk: flutter @@ -23,4 +24,4 @@ dev_dependencies: flutter: uses-material-design: true assets: - - assets/fake_map.png + - assets/ diff --git a/package/README.md b/package/README.md index f97ec8eb..4fd380b3 100644 --- a/package/README.md +++ b/package/README.md @@ -17,6 +17,10 @@ > > This library is currently in the experimental stage. The API may undergo changes without prior notice. +> [!NOTE] +> +> For documentation of the latest published version, please visit the [package page](https://pub.dev/packages/smooth_sheets) on pub.dev. +
## Showcases @@ -27,12 +31,24 @@

AI Playlist Generator

An AI assistant that helps create a music playlist based on the user's preferences. See the cookbook for more details.

-

Used components:

+

Key components:

+ + + + + +

Safari app

+

A practical example of ios-style modal sheets. See the cookbook for more details.

+

Key components:

+ @@ -40,13 +56,12 @@

Airbnb mobile app clone

-

A partial clone of the Airbnb mobile app. The user can drag the house list down to reveal the map behind it. See the cookbook for more details.

-

Used components:

+

A partial clone of the Airbnb mobile app. The user can drag the house list down to reveal the map behind it. See the cookbook for more details.

+

Key components:

@@ -55,7 +70,7 @@

Todo List

-

A simple Todo app that shows how a sheet handles the on-screen keyboard. See the cookbook for more details.

+

A simple Todo app that shows how a sheet handles the on-screen keyboard. See the cookbook for more details.

Used components: