Dialogs
CDX dialogs are composed from five primitives: DialogShell glues them together, and ConfirmationDialog provides the four canonical flavors. Custom dialogs use the primitives directly.
Live examples
Open the full Dialogs example.
ConfirmationDialog
Four named factories cover the standard cases. Always invoked through Flutter's showDialog.
| Factory | Variant | Buttons |
|---|---|---|
.info | standard | OK |
.error | error | OK |
.confirm | primary | Cancel + Confirm |
.destructive | destructive | Cancel + Confirm (error palette) |
final result = await showDialog<bool>(
context: context,
builder: (_) => ConfirmationDialog.destructive(
title: 'Delete area?',
description: 'This action cannot be undone.',
confirmLabel: 'Delete',
onCancel: () => Navigator.of(context).pop(false),
onConfirm: () => Navigator.of(context).pop(true),
),
);
// Info — single OK button
await showDialog<void>(
context: context,
builder: (_) => ConfirmationDialog.info(
title: 'Submitted',
description: 'Your request has been submitted for approval.',
onDismiss: () => Navigator.of(context).pop(),
),
);Optional body
Both .confirm and .destructive accept a body widget rendered below the description — use it for inline forms, e-signature inputs, or additional context.
ConfirmationDialog.confirm(
title: 'Approve change',
description: 'Sign with your initials to approve.',
confirmLabel: 'Approve',
isDisabled: initials.value.isEmpty,
isLoading: store.isSubmitting,
onCancel: () => Navigator.of(context).pop(),
onConfirm: () async => await store.approve(initials.value),
body: TextField(
decoration: const InputDecoration(labelText: 'Initials'),
controller: initials,
),
)DialogShell
The base container — modal barrier, sizing, header divider, and footer auto-wiring. Use it directly when you need a custom body or footer layout.
showDialog<void>(
context: context,
builder: (_) => DialogShell(
title: 'Edit profile',
icon: FluentIcons.person_edit_24_regular,
width: 720,
maxHeight: 600,
headerActions: [Button.icon(icon: FluentIcons.history_24_regular, ...)],
footerMessage: const DialogMessage(
text: 'Changes apply immediately.',
severity: MessageSeverity.info,
),
actions: [
DialogAction.cancel(onPressed: () => Navigator.pop(context)),
DialogAction.primary(label: 'Save', onPressed: _save),
],
content: const ProfileForm(),
),
);Parameters
| Param | Type | Default |
|---|---|---|
title / titleWidget | String? / Widget? | One required |
icon / iconColor | IconData? / Color? | null |
variant | DialogVariant | standard |
content | Widget | required |
actions | List<DialogAction>? | null (no footer) |
headerActions | List<Widget>? | null |
footerMessage | DialogMessage? | null |
width | double? | 600 |
maxHeight | double? | 500 |
showCloseButton | bool? | variant default |
onClose | VoidCallback? | Navigator.pop |
Primitives
DialogVariant
enum DialogVariant { standard, primary, destructive, error }Drives header background and close-button visibility:
| Variant | Header bg | Default close button |
|---|---|---|
standard | surfaceContainerHighest + tinted icon circle | shown |
primary | primaryContainer + onPrimaryContainer foreground | hidden |
destructive | errorContainer + onErrorContainer | hidden |
error | errorContainer + onErrorContainer | shown |
DialogHeader
DialogHeader(
title: 'Edit area',
icon: FluentIcons.edit_24_regular,
variant: DialogVariant.primary,
onClose: () => Navigator.pop(context),
actions: [const _HistoryButton()],
leading: IconButton(icon: const Icon(FluentIcons.arrow_left_24_regular), onPressed: ...),
)leading is reserved for back-arrow affordances (used by CdxPanelPage). actions render before the close button.
DialogFooter / DialogAction
DialogFooter(
message: const DialogMessage(text: 'All fields required.', severity: MessageSeverity.warning),
actions: [
DialogAction.cancel(onPressed: () => Navigator.pop(context)),
DialogAction.primary(label: 'Save', icon: FluentIcons.save_24_regular, onPressed: _save),
],
)DialogAction factories — .cancel, .ok, .primary, .destructive. Each carries isLoading / isDisabled for primary/destructive variants.
DialogMessage / MessageSeverity
Inline message banner inside the footer. MessageSeverity.error / warning / success / info maps to the matching Container palette (errorContainer, tertiaryContainer, etc.).