All skills
lassejlv avatar

/build-gpui-apps

@52f4cfd
by Lasselassejlv/skills50 stars
1

Build, scaffold, refactor, debug, review, and validate native Rust desktop applications with GPUI. Recommend GPUI Kit and ask before adopting it; use gpui_kit imports after agreement, or preserve the chosen upstream GPUI stack. Includes the merged GPUI Kit component and design skills, full application/Base/Component/Shell documentation, coding and design guides, state, actions, async, input, accessibility, motion, themes, native integration, packaging, auto updates, testing, and production delivery. Use paper-to-gpui when the primary task is faithfully translating a selected Paper.design frame into an existing view.

Use this Skill: https://skilld.dev/gh/lassejlv/skills/build-gpui-apps

This session only. Nothing lands on disk.

referencesgpui-kitupstreamcomponentalert-dialog.md

≈5.6k tokens on demand. Your agent reads this file only when SKILL.md points to it.

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 Cancel action, invoking on_cancel callback
  • DialogAction: Wraps a button to trigger the Confirm action, invoking on_ok callback

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_ok and on_cancel callbacks
  • Cleaner, more declarative code
  • Supports returning false from 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 Buttons

Set the button text and variant directly on the dialog:

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.")
        .confirm()
        .ok_text("Delete")
        .ok_variant(ButtonVariant::Danger)
        .cancel_text("Keep")
        .on_ok(|_, window, cx| {
            window.push_notification("Account deleted", cx);
            true
        })
})

button_props takes the same properties as one value, for a configuration you want to build up or pass around. It overrides only the fields the value sets, so everything the dialog already carries — the Cancel button confirm asked for, a callback an earlier on_ok installed — survives, whatever the call order:

use gpui_kit::component::dialog::DialogButtonProps;

window.open_alert_dialog(cx, move |alert, _, _| {
    alert
        .title("Delete Account")
        .confirm()
        .button_props(
            DialogButtonProps::default()
                .ok_text("Delete")
                .ok_variant(ButtonVariant::Danger)
        )
})

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:

window.open_alert_dialog(cx, |alert, _, _| {
    alert
        .title("Processing")
        .description("A process is running. Click Continue to stop it or Cancel to keep waiting.")
        .confirm()
        .ok_text("Continue")
        .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)
confirm() Show OK and Cancel buttons
ok_text(text) Set OK button text, default "OK"
ok_variant(variant) Set OK button variant, default Primary
cancel_text(text) Set cancel button text, default "Cancel"
cancel_variant(variant) Set cancel button variant
button_props(props) Override the button properties the value sets, keep the rest
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

Every property is unset until a builder sets it, and an unset property keeps whatever the dialog already carries.

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 Confirm action on click
  • Invokes the on_ok callback
  • 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 Cancel action on click
  • Invokes the on_cancel callback
  • 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:

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.")
                .confirm()
                .ok_text("Delete")
                .ok_variant(ButtonVariant::Danger)
                .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

  1. 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
  2. Use DialogAction and DialogClose: Prefer wrapping buttons with DialogAction and DialogClose over manual window.close_dialog() calls for cleaner, more declarative code
  3. Clarify Intent: Use appropriate button variants (e.g., ButtonVariant::Danger for delete operations) to communicate the importance of actions
  4. Provide Clear Descriptions: Ensure users understand the consequences of their actions, especially for destructive operations
  5. Use Icons Wisely: Icons can enhance attention for warnings and errors, but use them appropriately
  6. Prevent Closing Carefully: Only prevent dialog closing when user confirmation is truly necessary (e.g., a process is running)
  7. Maintain Consistency: Keep dialog button order and styles consistent throughout your application

Related Components

Documentation license: original prose and illustrations for which GPUI Kit holds licensing rights are also offered under CC BY 4.0. When copying or adapting, credit GPUI Kit, link the source (https://gpui-kit.com/component/alert-dialog) and https://creativecommons.org/licenses/by/4.0/, and indicate changes. Code examples and software source use Apache-2.0; third-party material retains its terms; existing Apache-2.0 permissions remain.

Bundled from GPUI Kit. Documentation prose: CC BY 4.0; code examples: Apache-2.0. Changes: documentation links localized, asset URLs made absolute, and this attribution added.

Source: SKILL.md on GitHub

No alerts3d3 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation and reference material for building native desktop applications using Rust and GPUI. No security risks, prompt injections, or malicious behaviors were identified. External dependencies originate from reputable organizations in the Rust ecosystem.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

Signed by skilld at 52f4cfd. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 4 days ago

README badge

README badge for lassejlv/skills/build-gpui-apps