fluttercnfluttercn
Components

Bottom Sheet

A modal or persistent overlay that slides up from the bottom of the screen

Installation

fluttercn add bottom-sheet

Usage

Basic Bottom Sheet

Simple modal bottom sheet with content:

Basic bottom sheet preview
showAppBottomSheet(
  context: context,
  builder: (context) => BottomSheetContent(
    child: Text('Bottom sheet content goes here'),
  ),
)

Bottom Sheet with Header

Bottom sheet with title, description, and close button:

Bottom sheet with header preview
showAppBottomSheet(
  context: context,
  builder: (context) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      BottomSheetHeader(
        title: BottomSheetTitle('Sheet Title'),
        description: BottomSheetDescription('Description goes here'),
        showCloseButton: true,
      ),
      BottomSheetContent(
        child: Text('Your content here'),
      ),
    ],
  ),
)

Bottom Sheet Sizes

Four predefined sizes for different content heights:

Bottom sheet sizes preview
// Small - 30% of screen height
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.sm,
  builder: (context) => YourContent(),
)
 
// Medium - 50% of screen height (default)
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.md,
  builder: (context) => YourContent(),
)
 
// Large - 75% of screen height
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.lg,
  builder: (context) => YourContent(),
)
 
// Full - 95% of screen height
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.full,
  builder: (context) => YourContent(),
)

Scrollable Content

For long content that needs scrolling:

Scrollable bottom sheet preview
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.lg,
  builder: (context) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      BottomSheetHeader(
        title: BottomSheetTitle('Long Content'),
        showCloseButton: true,
      ),
      BottomSheetContent(
        scrollable: true,
        child: Column(
          children: [
            // Your long content here
            ...List.generate(20, (index) => 
              ListTile(title: Text('Item $index')),
            ),
          ],
        ),
      ),
    ],
  ),
)

Add action buttons in a footer section:

Bottom sheet with footer preview
showAppBottomSheet(
  context: context,
  builder: (context) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      BottomSheetHeader(
        title: BottomSheetTitle('Confirm Action'),
        description: BottomSheetDescription('Please confirm your choice'),
      ),
      BottomSheetContent(
        child: Text('This action cannot be undone'),
      ),
      BottomSheetFooter(
        child: BottomSheetActions(
          secondaryAction: Button(
            variant: ButtonVariant.outline,
            onPressed: () => Navigator.pop(context),
            child: Text('Cancel'),
          ),
          primaryAction: Button(
            onPressed: () => Navigator.pop(context, true),
            child: Text('Confirm'),
          ),
        ),
      ),
    ],
  ),
)

Examples

Form Bottom Sheet

Form bottom sheet preview
showAppBottomSheet(
  context: context,
  size: BottomSheetSize.lg,
  builder: (context) => Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      BottomSheetHeader(
        title: BottomSheetTitle('Edit Profile'),
        showCloseButton: true,
      ),
      BottomSheetContent(
        child: Column(
          children: [
            TextField(
              label: 'Name',
              placeholder: 'Enter your name',
            ),
            SizedBox(height: AppTheme.spaceMd),
            TextField(
              label: 'Email',
              placeholder: 'Enter your email',
            ),
            SizedBox(height: AppTheme.spaceMd),
            TextField(
              label: 'Bio',
              placeholder: 'Tell us about yourself',
              maxLines: 3,
            ),
          ],
        ),
      ),
      BottomSheetFooter(
        child: BottomSheetActions(
          secondaryAction: Button(
            variant: ButtonVariant.outline,
            fullWidth: true,
            onPressed: () => Navigator.pop(context),
            child: Text('Cancel'),
          ),
          primaryAction: Button(
            fullWidth: true,
            onPressed: () {
              // Save changes
              Navigator.pop(context);
            },
            child: Text('Save'),
          ),
        ),
      ),
    ],
  ),
)

API Reference

showAppBottomSheet

PropertyTypeDefaultDescription
contextBuildContextrequiredBuild context
builderWidgetBuilderrequiredBuilder function for sheet content
sizeBottomSheetSizemdPredefined height
isScrollControlledbooltrueAllow custom height control
isDismissiblebooltrueAllow dismiss by tapping outside
enableDragbooltrueEnable swipe to dismiss
useSafeAreabooltrueRespect safe areas
resizeToAvoidBottomInsetbooltrueResize when keyboard appears
backgroundColorColor?transparentBackground color
barrierColorColor?black54Overlay backdrop color
constraintsBoxConstraints?nullCustom size constraints

showPersistentAppBottomSheet

PropertyTypeDefaultDescription
contextBuildContextrequiredBuild context
builderWidgetBuilderrequiredBuilder function for sheet content
backgroundColorColor?surfaceBackground color
enableDragbooltrueEnable swipe to dismiss
constraintsBoxConstraints?nullCustom size constraints

showConfirmationBottomSheet

PropertyTypeDefaultDescription
contextBuildContextrequiredBuild context
titleStringrequiredConfirmation title
descriptionStringrequiredConfirmation description
confirmTextStringConfirmConfirm button text
cancelTextStringCancelCancel button text
isDestructiveboolfalseUse destructive styling for confirm
iconWidget?nullOptional icon above title

BottomSheetHeader

PropertyTypeDefaultDescription
titleBottomSheetTitle?nullTitle widget
descriptionBottomSheetDescription?nullDescription widget
childWidget?nullCustom header content (cannot use with title/description)
showCloseButtonboolfalseShow close button
onCloseVoidCallback?nullCustom close handler
paddingEdgeInsets?nullCustom padding

BottomSheetTitle

PropertyTypeDefaultDescription
textStringrequiredThe title text
styleTextStyle?nullCustom text style

BottomSheetDescription

PropertyTypeDefaultDescription
textStringrequiredThe description text
styleTextStyle?nullCustom text style

BottomSheetContent

PropertyTypeDefaultDescription
childWidgetrequiredContent widget
scrollableboolfalseEnable scrolling
paddingEdgeInsets?nullCustom padding
physicsScrollPhysics?nullScroll physics
scrollControllerScrollController?nullExternal scroll controller

BottomSheetFooter

PropertyTypeDefaultDescription
childWidgetrequiredFooter widget
paddingEdgeInsets?nullCustom padding

BottomSheetActions

PropertyTypeDefaultDescription
primaryActionWidget?nullPrimary action button
secondaryActionWidget?nullSecondary action button
spacingdoubleAppTheme.spaceMdSpace between buttons
directionAxishorizontalLayout direction
mainAxisAlignmentMainAxisAlignmentendAlignment for horizontal layout

BottomSheetLoadingOverlay

PropertyTypeDefaultDescription
isLoadingboolrequiredWhether to show loading
childWidgetrequiredContent widget
loadingWidgetWidget?nullCustom loading indicator
loadingTextString?nullOptional loading text

BottomSheetSize

  • sm - Small (30% of screen height)
  • md - Medium (50% of screen height, default)
  • lg - Large (75% of screen height)
  • full - Full (95% of screen height)

Features

  • Multiple Sizes - Four predefined sizes for different content heights
  • Scrollable Content - Built-in scroll support for long content
  • Composable Structure - Separate header, content, and footer sections
  • Keyboard Aware - Automatically adjusts for keyboard
  • Safe Areas - Respects device safe areas and notches
  • Drag Handle - Visual indicator for swipe gestures
  • Confirmation Template - Pre-built confirmation dialog
  • Loading States - Built-in loading overlay component
  • Persistent Mode - Non-modal sheets that don't block interaction
  • Themed - Automatically adapts to light/dark mode

Bottom sheets automatically handle keyboard appearance and safe areas. The content will resize and adjust to avoid being hidden behind the keyboard or system UI.

When using BottomSheetContent with scrollable: true, avoid nesting scrollable widgets as this can cause gesture conflicts.

Best Practices

  • Use BottomSheetSize.sm for simple confirmations or quick actions
  • Use BottomSheetSize.md for forms with a few fields
  • Use BottomSheetSize.lg for longer forms or lists
  • Use BottomSheetSize.full for complex multi-step flows
  • Always provide a way to dismiss (close button or swipe)
  • Use showConfirmationBottomSheet for destructive actions
  • Enable scrollable for content that might overflow
  • Use BottomSheetActions for consistent button layouts
  • Show loading states with BottomSheetLoadingOverlay
  • Use persistent sheets for non-modal overlays that shouldn't block interaction