crisp_dialog

Production-grade Flutter dialogs with async-aware buttons, design-system theming, and a composable API.

await CrispDialog.confirm(
  context: context,
  title: 'Delete Record',
  description: 'This cannot be undone.',
  onConfirm: () async {
    await api.deleteRecord(id);
  },
);

When onConfirm returns a Future, the button automatically shows a spinner, disables sibling buttons, and handles errors inline — no wrapper code needed.


Features

  • Async-aware buttons — return a Future from any callback and the dialog handles loading/error states automatically.
  • Design-system theming — global styling via ThemeExtension. Set once in MaterialApp, applied everywhere.
  • Composable API — named static methods (confirm, info, warning, error, success, custom) instead of a single god-object constructor.
  • Zero dependencies — no Lottie, no Rive, no animation libs. Headers are widget slots — bring your own.
  • Inline error display — async failures show an error message inside the dialog. No crash, no auto-dismiss. Users can retry.
  • Light & dark presetsCrispDialogTheme.light() and .dark() for quick setup.

Installation

dependencies:
  crisp_dialog: ^0.1.0
import 'package:crisp_dialog/crisp_dialog.dart';

Dialog Types

Confirm

Two-button dialog for confirm/cancel flows.

await CrispDialog.confirm(
  context: context,
  title: 'Submit Payment',
  description: 'Process \$49.99 charge?',
  confirmText: 'Pay Now',
  cancelText: 'Cancel',
  onConfirm: () async {
    await paymentService.charge(amount);
  },
);

Info

Single-button informational dialog.

await CrispDialog.info(
  context: context,
  title: 'App Updated',
  description: 'Version 2.4.0 installed.',
);

Warning

Confirm/cancel with warning styling.

await CrispDialog.warning(
  context: context,
  title: 'Unsaved Changes',
  description: 'Leaving will discard your work.',
  confirmText: 'Discard',
);

Error

Single dismiss button with error styling.

await CrispDialog.error(
  context: context,
  title: 'Upload Failed',
  description: 'File exceeds the 25 MB limit.',
);

Success

Auto-dismisses after a duration, or shows a button.

await CrispDialog.success(
  context: context,
  title: 'Appointment Booked',
  autoDismiss: const Duration(seconds: 2),
);

Custom

Full control — bring your own body and actions.

await CrispDialog.custom(
  context: context,
  title: 'Rate This App',
  body: StarRatingWidget(),
  actions: [
    CrispDialogAction(label: 'Submit', onPressed: () async { ... }),
    CrispDialogAction(label: 'Later', style: CrispActionStyle.secondary),
  ],
);

Async Button Behavior

When any action callback returns a Future:

  1. The button shows a CircularProgressIndicator in place of its label.
  2. All sibling buttons are disabled.
  3. On success → dialog auto-dismisses (if autoDismiss: true).
  4. On failure → an inline error message appears below the buttons. The dialog stays open so the user can retry.
  5. The error is clearable with a tap.

Theming

MaterialApp(
  theme: ThemeData(
    extensions: [
      CrispDialogTheme(
        borderRadius: BorderRadius.circular(20),
        animationType: CrispAnimationType.slideUp,
        primaryButtonTheme: CrispButtonTheme(
          backgroundColor: Color(0xFF0057FF),
        ),
      ),
    ],
  ),
);

Presets

// Light preset
ThemeData(extensions: [CrispDialogTheme.light()])

// Dark preset
ThemeData(extensions: [CrispDialogTheme.dark()])

Per-Dialog Override

await CrispDialog.confirm(
  context: context,
  title: 'Override',
  theme: CrispDialogTheme(
    animationType: CrispAnimationType.fade,
  ),
);

Theme resolution order: per-dialog override → global ThemeExtension → built-in defaults.


Animation Types

Type Description
CrispAnimationType.scale Scale up from center (default)
CrispAnimationType.slideUp Slide up from bottom
CrispAnimationType.slideRight Slide in from left
CrispAnimationType.fade Fade in

Custom Headers

The header is a widget slot — pass any widget you want:

await CrispDialog.success(
  context: context,
  title: 'Booked!',
  header: LottieBuilder.asset('assets/success.json'),
);

Requirements

  • Flutter >= 3.10.0
  • Dart >= 3.0.0
  • Zero runtime dependencies

License

MIT

Libraries

crisp_dialog
Production-grade Flutter dialogs with async-aware buttons, design-system theming, and a composable API.