Dialog
A modal dialog component for focused decisions, confirmations, and custom content
A modal dialog component for focused content and actions.
When to use this
- Confirmations: Ask users to confirm destructive or important actions
- Focused forms: Collect a small amount of information without leaving the current screen
- Alerts: Present information that needs immediate attention
- Custom modal content: Render a fully custom body inside Remix dialog chrome
Basic implementation
Basic implementation
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
import 'ui/ui.dart';
class DialogExample extends StatelessWidget {
const DialogExample({super.key});
@override
Widget build(BuildContext context) {
return FortalButton(
label: 'Open dialog',
onPressed: () {
showRemixDialog(
context: context,
builder: (context) => FortalDialog(
title: 'Revoke access',
description:
'This application will no longer be accessible.',
actions: [
FortalButton.ghost(
label: 'Cancel',
onPressed: () => Navigator.pop(context),
),
FortalButton(
label: 'Revoke access',
onPressed: () => Navigator.pop(context),
),
],
),
);
},
);
}
}Alert dialogs
Use showRemixAlertDialog for urgent or destructive confirmations. It requires
a localized semantic label, keeps barrier dismissal disabled by default, moves
focus into the alert, and lets Escape or platform Back cancel safely. A nested
RemixDialog automatically reuses the alert semantics wrapper, so no additional
configuration is needed.
Destructive alert
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
import 'ui/ui.dart';
Future<void> showDeleteDialog(BuildContext context) async {
await showRemixAlertDialog<void>(
context: context,
semanticLabel: 'Delete project confirmation',
builder: (context) => FortalDialog(
title: 'Delete project?',
description: 'This permanently deletes the project and all of its data.',
actions: [
FortalButton.ghost(
label: 'Cancel',
onPressed: () => Navigator.pop(context),
),
FortalButton(
label: 'Delete project',
onPressed: () => Navigator.pop(context),
),
],
),
);
}Fortal widgets
The application-owned Fortal preset provides a themed widget for this component:
FortalDialog defaults to FortalDialogSize.size3,
Alignment.center, fills the available width up to 600 logical pixels,
preserves safe viewport insets, and uses modal: true. Set
align: Alignment.topCenter to place the surface at the safe top inset.
Fortal widget
import 'package:flutter/material.dart';
import 'ui/ui.dart';
class FortalDialogExample extends StatelessWidget {
const FortalDialogExample({super.key});
@override
Widget build(BuildContext context) {
return FortalDialog(
align: Alignment.center,
title: 'Confirm changes',
description: 'Save these settings before leaving?',
actions: [
FortalButton.ghost(
label: 'Cancel',
onPressed: () => Navigator.pop(context),
),
FortalButton(
label: 'Save',
onPressed: () => Navigator.pop(context),
),
],
);
}
}See the fortalDialogStyle source code for all available options.
Show function
showRemixDialog
Future<T?> showRemixDialog<T>({
required BuildContext context,
required WidgetBuilder builder,
Color? barrierColor,
bool barrierDismissible = true,
String? barrierLabel,
bool useRootNavigator = true,
RouteSettings? routeSettings,
Offset? anchorPoint,
Duration transitionDuration = const Duration(milliseconds: 400),
RouteTransitionsBuilder? transitionBuilder,
bool requestFocus = true,
TraversalEdgeBehavior? traversalEdgeBehavior,
})showRemixAlertDialog
Future<T?> showRemixAlertDialog<T>({
required BuildContext context,
required WidgetBuilder builder,
required String semanticLabel,
Color? barrierColor,
String? barrierLabel,
bool barrierDismissible = false,
bool useRootNavigator = true,
RouteSettings? routeSettings,
Offset? anchorPoint,
Duration transitionDuration = const Duration(milliseconds: 400),
RouteTransitionsBuilder? transitionBuilder,
FocusNode? initialFocusNode,
})semanticLabel must be a non-empty, localized description of the alert.
barrierColor defaults to Colors.black54. If barrierDismissible is enabled,
provide a non-empty localized barrierLabel as well.
An initialFocusNode remains owned by the caller and should be attached to a
focusable widget inside the alert. If it is omitted, focus uses an autofocus
request or the first traversable descendant. Escape and platform Back dismiss
the alert with a null result.
Constructor
Constructor
import 'package:flutter/material.dart';
import 'package:remix/remix.dart';
RemixDialog remixDialogConstructor({
Key? key,
Widget? child,
String? title,
String? description,
List<Widget>? actions,
bool modal = true,
bool scrollable = false,
String? semanticLabel,
DialogStyler style = const DialogStyler.create(),
DialogSpec? styleSpec,
}) => throw UnimplementedError();Properties
Widget Properties
child -> Widget?
Optional. Custom dialog content rendered after the description and before the actions. When it is the only content provided, it fills the container directly.
title -> String?
Optional. The dialog title text. Either child, title, or description must be provided.
description -> String?
Optional. Supporting body text rendered below the title.
actions -> List<Widget>?
Optional. Action widgets rendered in the dialog actions row.
modal -> bool
Optional. Whether the dialog blocks interaction with background content.
scrollable -> bool
Optional. When true, description and child share a vertical scroll region while title and actions remain outside it. A lone child is never wrapped in the scroll region.
semanticLabel → String?
Optional. Accessibility label for the dialog. Defaults to the title when omitted.
style → DialogStyler
Optional. The style configuration for the dialog container, title, description, and actions.
styleSpec → DialogSpec?
Optional. A raw resolved style spec that bypasses fluent style resolution.
Style Methods
container(BoxStyler value)
Configures the dialog container style.
title(TextStyler value)
Configures the title text style.
description(TextStyler value)
Configures the description text style.
actions(FlexBoxStyler value)
Configures the actions row style.
padding(EdgeInsetsGeometryMix value)
Sets dialog container padding.
borderRadius(BorderRadiusGeometryMix radius)
Sets dialog container border radius.
shadow(BoxShadowMix value)
Sets dialog container shadow.
wrap(WidgetModifierConfig value)
Applies widget modifiers such as clipping, opacity, or scaling.
call({Key? key, Widget? child, String? title, String? description, List<Widget>? actions, bool modal = true, String? semanticLabel})
Creates a RemixDialog widget with this style applied.
Alignment API migration
These are source-breaking replacements with no deprecated aliases. Parameter
names (alignment, align, and iconAlignment) are unchanged.
| Previous API | Replacement |
|---|---|
RemixDataListItemAlignment.* | CrossAxisAlignment.* (same five values) |
RemixDataTableCellAlignment.start | AlignmentDirectional.centerStart |
RemixDataTableCellAlignment.center | Alignment.center |
RemixDataTableCellAlignment.end | AlignmentDirectional.centerEnd |
FortalDialogAlign.start | Alignment.topCenter |
FortalDialogAlign.center | Alignment.center |
RemixIconAlignment.start/end | RemixPlacement.start/end |
AgentMessageAlign.start/end (including installed prefixes) | RemixPlacement.start/end |
Import Flutter alignment types from package:flutter/widgets.dart and shared
RemixPlacement from package:remix/remix.dart. Refresh installed dialog and
message components with the CLI, preserving any application-owned customizations.
The shared placement type is not renamed with the installed component prefix.
Dialog align accepts any AlignmentGeometry, such as Alignment.bottomCenter
or AlignmentDirectional.bottomEnd. Directional positions follow RTL; physical
positions do not. All positions retain the same safe-area and viewport insets.