AlertDialog
AlertDialog is a modal dialog component that interrupts the user with important content and expects a response. It is built on top of the Dialog component with opinionated defaults and a simplified API.
#Differences from Dialog
AlertDialog provides these defaults on top of Dialog:
- Not overlay closable by default (can be changed with
overlay_closable(true)) - No close button by default (can be changed with
close_button(true)) - Footer buttons are center-aligned (Dialog uses right-alignment)
- Simplified API focused on alert and confirmation scenarios
#Import
use gpui_kit::component::dialog::{AlertDialog, DialogAction, DialogClose};
use gpui_kit::component::WindowExt;
#Usage
#Setup Application Root View
Like Dialog, you need to set up your application’s root view to render the dialog layer. See Dialog documentation for details.
#Basic AlertDialog (Declarative API)
Create a fully declarative AlertDialog using trigger and content:
use gpui_kit::component::dialog::{AlertDialog, DialogHeader, DialogTitle, DialogDescription, DialogFooter};
AlertDialog::new(cx)
.trigger(
Button::new("show-alert")
.outline()
.label("Show Alert")
)
.content(|content, _, cx| {
content
.child(
DialogHeader::new()
.child(DialogTitle::new().child("Are you absolutely sure?"))
.child(DialogDescription::new().child(
"This action cannot be undone. \
This will permanently delete your account from our servers."
))
)
.child(
DialogFooter::new()
.child(
Button::new("cancel")
.outline()
.label("Cancel")
.on_click(|_, window, cx| {
window.close_dialog(cx);
})
)
.child(
Button::new("ok")
.primary()
.label("Continue")
.on_click(|_, window, cx| {
window.push_notification("Confirmed", cx);
window.close_dialog(cx);
})
)
)
})
#Using DialogAction and DialogClose
DialogAction and DialogClose are wrapper components that simplify button click handling by automatically triggering the appropriate actions:
- DialogClose: Wraps a button to trigger the
Cancelaction, invokingon_cancelcallback - DialogAction: Wraps a button to trigger the
Confirmaction, invokingon_okcallback
These components eliminate the need to manually call window.close_dialog(cx):
AlertDialog::new(cx)
.trigger(Button::new("show-alert").outline().label("Show Alert"))
.on_ok(|_, window, cx| {
window.push_notification("You confirmed!", cx);
true // Return true to close dialog
})
.on_cancel(|_, window, cx| {
window.push_notification("You cancelled!", cx);
true
})
.content(|content, _, cx| {
content
.child(
DialogHeader::new()
.child(DialogTitle::new().child("Confirm Action"))
.child(DialogDescription::new().child("Do you want to proceed?"))
)
.child(
DialogFooter::new()
.child(
DialogClose::new().child(
Button::new("cancel").outline().label("Cancel")
)
)
.child(
DialogAction::new().child(
Button::new("ok").primary().label("Confirm")
)
)
)
})
Benefits:
- No need to manually close the dialog
- Automatically connects to
on_okandon_cancelcallbacks - Cleaner, more declarative code
- Supports returning
falsefrom callbacks to prevent closing
#Basic AlertDialog (Imperative API)
Open a dialog imperatively using WindowExt::open_alert_dialog:
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Delete File")
.description("Are you sure you want to delete this file? This action cannot be undone.")
.show_cancel(true)
.on_ok(|_, window, cx| {
window.push_notification("File deleted", cx);
true // Return true to close dialog
})
})
#Custom Button Props
Use button_props to customize button text and styles:
use gpui_kit::component::dialog::DialogButtonProps;
use gpui_kit::component::button::ButtonVariant;
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Delete Account")
.description("This will permanently delete your account and all associated data.")
.button_props(
DialogButtonProps::default()
.ok_text("Delete")
.ok_variant(ButtonVariant::Danger)
.cancel_text("Keep")
.show_cancel(true)
)
.on_ok(|_, window, cx| {
window.push_notification("Account deleted", cx);
true
})
})
#AlertDialog with Icon
Using icon in declarative API:
use gpui_kit::component::{Icon, IconName, ActiveTheme};
AlertDialog::new(cx)
.w(px(320.))
.trigger(Button::new("permission").outline().label("Request Permission"))
.on_ok(|_, window, cx| {
window.push_notification("Permission granted", cx);
true
})
.content(|content, _, cx| {
content
.child(
DialogHeader::new()
.items_center()
.child(
Icon::new(IconName::TriangleAlert)
.size_10()
.text_color(cx.theme().warning)
)
.child(DialogTitle::new().child("Network Permission Required"))
.child(DialogDescription::new().child(
"We need your permission to access the network to provide better services."
))
)
.child(
DialogFooter::new()
.v_flex()
.child(
DialogAction::new().child(
Button::new("allow").w_full().primary().label("Allow")
)
)
.child(
DialogClose::new().child(
Button::new("deny").w_full().outline().label("Don't Allow")
)
)
)
})
Using icon in imperative API:
window.open_alert_dialog(cx, |alert, _, cx| {
alert
.title("Warning")
.description("This action requires confirmation.")
.icon(
Icon::new(IconName::AlertTriangle)
.size_8()
.text_color(cx.theme().warning)
)
})
#Destructive Action Confirmation
AlertDialog::new(cx)
.trigger(
Button::new("delete-account")
.outline()
.danger()
.label("Delete Account")
)
.on_ok(|_, window, cx| {
window.push_notification("Account deletion initiated", cx);
true
})
.content(|content, _, _| {
content
.child(
DialogHeader::new()
.child(DialogTitle::new().child("Delete Account"))
.child(DialogDescription::new().child(
"This will permanently delete your account \
and all associated data. This action cannot be undone."
))
)
.child(
DialogFooter::new()
.child(
DialogClose::new().child(
Button::new("cancel").flex_1().outline().label("Cancel")
)
)
.child(
DialogAction::new().child(
Button::new("delete")
.flex_1()
.outline()
.danger()
.label("Delete Forever")
)
)
)
})
#Custom Width
AlertDialog::new(cx)
.width(px(500.))
.trigger(Button::new("custom-width").label("Custom Width"))
.content(|content, _, _| {
// ... dialog content
})
#Controlling Dialog Close Behavior
#Allow Overlay Click to Close
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Notice")
.description("Click outside this dialog or press ESC to close it.")
.overlay_closable(true)
})
#Disable Keyboard ESC to Close
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Important Notice")
.description("Please read this carefully before proceeding.")
.keyboard(false)
})
#Show Close Button
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Information")
.description("Some information...")
.close_button(true)
})
#Prevent Dialog from Closing
Return false from on_ok or on_cancel callbacks to prevent the dialog from closing:
use gpui_kit::component::dialog::DialogButtonProps;
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Processing")
.description("A process is running. Click Continue to stop it or Cancel to keep waiting.")
.button_props(
DialogButtonProps::default()
.ok_text("Continue")
.show_cancel(true)
)
.on_ok(|_, window, cx| {
// Return false to prevent closing
window.push_notification("Cannot close: Process still running", cx);
false
})
.on_cancel(|_, window, cx| {
window.push_notification("Waiting...", cx);
false
})
})
#Dialog Close Callback
Use on_close to execute actions after the dialog closes (called after on_ok or on_cancel):
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Confirm")
.description("Are you sure?")
.on_close(|_, window, cx| {
window.push_notification("Dialog closed", cx);
})
})
#API Reference
#AlertDialog
| Method | Description |
|---|---|
new(cx) | Create a new AlertDialog |
trigger(element) | Set trigger element that opens the dialog when clicked |
content(builder) | Set dialog content using a builder function (declarative API) |
title(title) | Set dialog title (imperative API) |
description(desc) | Set dialog description (imperative API) |
icon(icon) | Set dialog icon (imperative API) |
button_props(props) | Set button properties (text, style, visibility) |
show_cancel(bool) | Show/hide cancel button, default false |
width(px) | Set dialog width, default 420px |
overlay_closable(bool) | Allow clicking overlay to close, default false |
close_button(bool) | Show/hide close button, default false |
keyboard(bool) | Support ESC key to close, default true |
on_ok(callback) | Set OK button callback, return true to close dialog |
on_cancel(callback) | Set cancel button callback, return true to close dialog |
on_close(callback) | Set callback after dialog closes |
#DialogButtonProps
| Method | Description |
|---|---|
ok_text(text) | Set OK button text, default “OK” |
cancel_text(text) | Set cancel button text, default “Cancel” |
ok_variant(variant) | Set OK button variant |
cancel_variant(variant) | Set cancel button variant |
show_cancel(bool) | Show/hide cancel button |
on_ok(callback) | Set OK callback |
on_cancel(callback) | Set cancel callback |
#DialogAction
A wrapper component that automatically triggers the Confirm action when its child element is clicked. This invokes the on_ok callback set on the AlertDialog.
Usage:
DialogAction::new().child(
Button::new("ok").primary().label("Confirm")
)
Behavior:
- Dispatches
Confirmaction on click - Invokes the
on_okcallback - Dialog closes if callback returns
true - Dialog stays open if callback returns
false
#DialogClose
A wrapper component that automatically triggers the Cancel action when its child element is clicked. This invokes the on_cancel callback set on the AlertDialog.
Usage:
DialogClose::new().child(
Button::new("cancel").outline().label("Cancel")
)
Behavior:
- Dispatches
Cancelaction on click - Invokes the
on_cancelcallback - Dialog closes if callback returns
true(or if no callback is set) - Dialog stays open if callback returns
false
#Examples
#Delete Confirmation
Using imperative API with button props:
Button::new("delete")
.danger()
.label("Delete")
.on_click(|_, window, cx| {
window.open_alert_dialog(cx, |alert, _, _| {
alert
.title("Delete File?")
.description("This action cannot be undone.")
.button_props(
DialogButtonProps::default()
.ok_text("Delete")
.ok_variant(ButtonVariant::Danger)
.show_cancel(true)
)
.on_ok(|_, window, cx| {
// Perform delete operation
window.push_notification("File deleted", cx);
true
})
});
})
Or using declarative API with DialogAction/DialogClose:
AlertDialog::new(cx)
.trigger(Button::new("delete").danger().label("Delete"))
.on_ok(|_, window, cx| {
window.push_notification("File deleted", cx);
true
})
.content(|content, _, cx| {
content
.child(
DialogHeader::new()
.child(DialogTitle::new().child("Delete File?"))
.child(DialogDescription::new().child("This action cannot be undone."))
)
.child(
DialogFooter::new()
.child(
DialogClose::new().child(
Button::new("cancel").outline().label("Cancel")
)
)
.child(
DialogAction::new().child(
Button::new("delete-confirm").danger().label("Delete")
)
)
)
})
#Session Timeout
window.open_alert_dialog(cx, |alert, _, _| {
alert
.content(|content, _, _| {
content
.child(
DialogHeader::new()
.items_center()
.child(DialogTitle::new().child("Session Expired"))
.child(DialogDescription::new().child(
"Your session has expired due to inactivity. \
Please log in again to continue."
))
)
.child(
DialogFooter::new()
.child(
Button::new("sign-in")
.label("Sign in")
.primary()
.flex_1()
.on_click(|_, window, cx| {
window.push_notification("Redirecting to login...", cx);
window.close_dialog(cx);
})
)
)
})
})
#Update Available
AlertDialog::new(cx)
.trigger(Button::new("update").outline().label("Update Available"))
.on_cancel(|_, window, cx| {
window.push_notification("Update postponed", cx);
true
})
.on_ok(|_, window, cx| {
window.push_notification("Starting update...", cx);
true
})
.content(|content, _, _| {
content
.child(
DialogHeader::new()
.child(DialogTitle::new().child("Update Available"))
.child(DialogDescription::new().child(
"A new version (v2.0.0) is available. \
This update includes new features and bug fixes."
))
)
.child(
DialogFooter::new()
.child(
DialogClose::new().child(
Button::new("later").flex_1().outline().label("Later")
)
)
.child(
DialogAction::new().child(
Button::new("update-now").flex_1().primary().label("Update Now")
)
)
)
})
#Best Practices
- Choose the Right API: Use imperative API (
open_alert_dialog) for simple confirmations; use declarative API (trigger+content) for complex layouts or integration with other components - Use DialogAction and DialogClose: Prefer wrapping buttons with
DialogActionandDialogCloseover manualwindow.close_dialog()calls for cleaner, more declarative code - Clarify Intent: Use appropriate button variants (e.g.,
ButtonVariant::Dangerfor delete operations) to communicate the importance of actions - Provide Clear Descriptions: Ensure users understand the consequences of their actions, especially for destructive operations
- Use Icons Wisely: Icons can enhance attention for warnings and errors, but use them appropriately
- Prevent Closing Carefully: Only prevent dialog closing when user confirmation is truly necessary (e.g., a process is running)
- Maintain Consistency: Keep dialog button order and styles consistent throughout your application
#Related Components
- Dialog - More flexible dialog component
- DialogHeader - Dialog header component
- DialogTitle - Dialog title component
- DialogDescription - Dialog description component
- DialogFooter - Dialog footer component
- DialogAction - Wrapper component for confirm/OK buttons
- DialogClose - Wrapper component for cancel/close buttons