Skip to content

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.

ConfirmationDialog

Four named factories cover the standard cases. Always invoked through Flutter's showDialog.

FactoryVariantButtons
.infostandardOK
.errorerrorOK
.confirmprimaryCancel + Confirm
.destructivedestructiveCancel + Confirm (error palette)
dart
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.

dart
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.

dart
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

ParamTypeDefault
title / titleWidgetString? / Widget?One required
icon / iconColorIconData? / Color?null
variantDialogVariantstandard
contentWidgetrequired
actionsList<DialogAction>?null (no footer)
headerActionsList<Widget>?null
footerMessageDialogMessage?null
widthdouble?600
maxHeightdouble?500
showCloseButtonbool?variant default
onCloseVoidCallback?Navigator.pop

Primitives

DialogVariant

dart
enum DialogVariant { standard, primary, destructive, error }

Drives header background and close-button visibility:

VariantHeader bgDefault close button
standardsurfaceContainerHighest + tinted icon circleshown
primaryprimaryContainer + onPrimaryContainer foregroundhidden
destructiveerrorContainer + onErrorContainerhidden
errorerrorContainer + onErrorContainershown

DialogHeader

dart
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

dart
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.).

  • ButtonsButton.icon for header actions
  • PanelsCdxPanelPage reuses DialogHeader + DialogFooter
  • ThemingcontainerBorderRadius for the dialog frame