Contribute

Edit this documentation

Translate the documentation or open the complete project on your computer.

Nothing is published until you choose to submit your work.

Message dialogs

Display information, warnings, errors, and questions

Message dialogs

Wails provides native message dialogs with platform-appropriate appearance: info, warning, error, and question dialogs with customisable titles, messages, and buttons. Simple API, native behaviour, accessible by default.

Creating Dialogs

Message dialogs are accessed through the app.Dialog manager:

go
app.Dialog.Info()
app.Dialog.Question()
app.Dialog.Warning()
app.Dialog.Error()

All methods return a *MessageDialog that can be configured using method chaining.

Information dialog

Display informational messages:

go
app.Dialog.Info().
    SetTitle("Success").
    SetMessage("File saved successfully!").
    Show()

Use cases:

  • Success confirmations
  • Completion notices
  • Informational messages
  • Status updates

Example - Save confirmation:

go
func saveFile(app *application.App, path string, data []byte) error {
    if err := os.WriteFile(path, data, 0644); err != nil {
        return err
    }

    app.Dialog.Info().
        SetTitle("File Saved").
        SetMessage(fmt.Sprintf("Saved to %s", filepath.Base(path))).
        Show()

    return nil
}

Warning dialog

Show warnings:

go
app.Dialog.Warning().
    SetTitle("Warning").
    SetMessage("This action cannot be undone.").
    Show()

Use cases:

  • Non-critical warnings
  • Deprecation notices
  • Caution messages
  • Potential issues

Example - Disk space warning:

go
func checkDiskSpace(app *application.App) {
    available := getDiskSpace()

    if available < 100*1024*1024 { // Less than 100MB
        app.Dialog.Warning().
            SetTitle("Low Disk Space").
            SetMessage(fmt.Sprintf("Only %d MB available.", available/(1024*1024))).
            Show()
    }
}

Error dialog

Display errors:

go
app.Dialog.Error().
    SetTitle("Error").
    SetMessage("Failed to connect to server.").
    Show()

Use cases:

  • Error messages
  • Failure notifications
  • Exception handling
  • Critical issues

Example - Network error:

go
func fetchData(app *application.App, url string) ([]byte, error) {
    resp, err := http.Get(url)
    if err != nil {
        app.Dialog.Error().
            SetTitle("Network Error").
            SetMessage(fmt.Sprintf("Failed to connect: %v", err)).
            Show()
        return nil, err
    }
    defer resp.Body.Close()

    return io.ReadAll(resp.Body)
}

Question dialog

Ask users questions and handle responses via button callbacks:

go
dialog := app.Dialog.Question().
    SetTitle("Confirm").
    SetMessage("Save changes before closing?")

save := dialog.AddButton("Save")
save.OnClick(func() {
    saveChanges()
})

dontSave := dialog.AddButton("Don't Save")
dontSave.OnClick(func() {
    // Continue without saving
})

cancel := dialog.AddButton("Cancel")
cancel.OnClick(func() {
    // Don't close
})

dialog.SetDefaultButton(save)
dialog.SetCancelButton(cancel)
dialog.Show()

Use cases:

  • Confirm actions
  • Yes/No questions
  • Multiple choice
  • User decisions

Example - Unsaved changes:

go
func closeDocument(app *application.App) {
    if !hasUnsavedChanges() {
        doClose()
        return
    }

    dialog := app.Dialog.Question().
        SetTitle("Unsaved Changes").
        SetMessage("Do you want to save your changes?")

    save := dialog.AddButton("Save")
    save.OnClick(func() {
        if saveDocument() {
            doClose()
        }
    })

    dontSave := dialog.AddButton("Don't Save")
    dontSave.OnClick(func() {
        doClose()
    })

    cancel := dialog.AddButton("Cancel")
    // Cancel button has no callback - just closes the dialog

    dialog.SetDefaultButton(save)
    dialog.SetCancelButton(cancel)
    dialog.Show()
}

dialog Options

Title and Message

go
dialog := app.Dialog.Info().
    SetTitle("Operation Complete").
    SetMessage("All files have been processed successfully.")

Best practices:

  • Title: Short, descriptive (2-5 words)
  • Message: Clear, specific, actionable
  • Avoid jargon: Use plain language

Buttons

Single button (Info/Warning/Error):

Info, warning, and error dialogs display a default “OK” button:

go
app.Dialog.Info().
    SetMessage("Done!").
    Show()

You can also add custom buttons:

go
dialog := app.Dialog.Info().
    SetMessage("Done!")
ok := dialog.AddButton("Got it!")
dialog.SetDefaultButton(ok)
dialog.Show()

Multiple buttons (Question):

Use AddButton() to add buttons, which returns a *Button you can configure:

go
dialog := app.Dialog.Question().
    SetMessage("Choose an action")

option1 := dialog.AddButton("Option 1")
option1.OnClick(func() {
    handleOption1()
})

option2 := dialog.AddButton("Option 2")
option2.OnClick(func() {
    handleOption2()
})

option3 := dialog.AddButton("Option 3")
option3.OnClick(func() {
    handleOption3()
})

dialog.Show()

Default and Cancel buttons:

Use SetDefaultButton() to specify which button is highlighted and triggered by Enter. Use SetCancelButton() to specify which button is triggered by Escape.

go
dialog := app.Dialog.Question().
    SetMessage("Delete file?")

deleteBtn := dialog.AddButton("Delete")
deleteBtn.OnClick(func() {
    performDelete()
})

cancelBtn := dialog.AddButton("Cancel")
// No callback needed - just dismisses dialog

dialog.SetDefaultButton(cancelBtn)  // Safe option as default
dialog.SetCancelButton(cancelBtn)   // Escape triggers Cancel
dialog.Show()

You can also use the fluent SetAsDefault() and SetAsCancel() methods on buttons:

go
dialog := app.Dialog.Question().
    SetMessage("Delete file?")

dialog.AddButton("Delete").OnClick(func() {
    performDelete()
})

dialog.AddButton("Cancel").SetAsDefault().SetAsCancel()

dialog.Show()

Best practices:

  • 1-3 buttons: Don’t overwhelm users
  • Clear labels: “Save” not “OK”
  • Safe default: Non-destructive action
  • Order matters: Most likely action first (except Cancel)

Custom Icon

Set a custom icon for the dialog:

go
app.Dialog.Info().
    SetTitle("Custom Icon Example").
    SetMessage("Using a custom icon").
    SetIcon(myIconBytes).
    Show()

Window Attachment

Attach to specific window:

go
dialog := app.Dialog.Question().
    SetMessage("Window-specific question").
    AttachToWindow(window)

dialog.AddButton("OK")
dialog.Show()

Benefits:

  • dialog appears on correct window
  • Parent window disabled whilst shown
  • Better multi-window UX

Complete Examples

Confirm Destructive Action

go
func deleteFiles(app *application.App, paths []string) {
    // Confirm deletion
    message := fmt.Sprintf("Delete %d file(s)?", len(paths))
    if len(paths) == 1 {
        message = fmt.Sprintf("Delete %s?", filepath.Base(paths[0]))
    }

    dialog := app.Dialog.Question().
        SetTitle("Confirm Delete").
        SetMessage(message)

    deleteBtn := dialog.AddButton("Delete")
    deleteBtn.OnClick(func() {
        // Perform deletion
        var errs []error
        for _, path := range paths {
            if err := os.Remove(path); err != nil {
                errs = append(errs, err)
            }
        }

        // Show result
        if len(errs) > 0 {
            app.Dialog.Error().
                SetTitle("Delete Failed").
                SetMessage(fmt.Sprintf("Failed to delete %d file(s)", len(errs))).
                Show()
        } else {
            app.Dialog.Info().
                SetTitle("Delete Complete").
                SetMessage(fmt.Sprintf("Deleted %d file(s)", len(paths))).
                Show()
        }
    })

    cancelBtn := dialog.AddButton("Cancel")
    dialog.SetDefaultButton(cancelBtn)
    dialog.SetCancelButton(cancelBtn)
    dialog.Show()
}

Quit Confirmation

go
func confirmQuit(app *application.App) {
    dialog := app.Dialog.Question().
        SetTitle("Quit").
        SetMessage("You have unsaved work. Are you sure you want to quit?")

    yes := dialog.AddButton("Yes")
    yes.OnClick(func() {
        app.Quit()
    })

    no := dialog.AddButton("No")
    dialog.SetDefaultButton(no)
    dialog.Show()
}

Update Dialog with Download Option

go
func showUpdateDialog(app *application.App) {
    dialog := app.Dialog.Question().
        SetTitle("Update").
        SetMessage("A new version is available. The cancel button is selected when pressing escape.")

    download := dialog.AddButton("📥 Download")
    download.OnClick(func() {
        app.Dialog.Info().SetMessage("Downloading...").Show()
    })

    cancel := dialog.AddButton("Cancel")

    dialog.SetDefaultButton(download)
    dialog.SetCancelButton(cancel)
    dialog.Show()
}

Custom Icon Question

go
func showCustomIconQuestion(app *application.App, iconBytes []byte) {
    dialog := app.Dialog.Question().
        SetTitle("Custom Icon Example").
        SetMessage("Using a custom icon").
        SetIcon(iconBytes)

    likeIt := dialog.AddButton("I like it!")
    likeIt.OnClick(func() {
        app.Dialog.Info().SetMessage("Thanks!").Show()
    })

    notKeen := dialog.AddButton("Not so keen...")
    notKeen.OnClick(func() {
        app.Dialog.Info().SetMessage("Too bad!").Show()
    })

    dialog.SetDefaultButton(likeIt)
    dialog.Show()
}

Best Practices

✅ Do

  • Be specific - “File saved to Documents” not “Success”
  • Use appropriate type - Error for errors, Warning for warnings
  • Provide context - Include relevant details
  • Use clear button labels - “Delete” not “OK”
  • Set safe defaults - Non-destructive action
  • Handle cancellation - User might close dialog

❌ Don’t

  • Don’t overuse - Interrupts workflow
  • Don’t use for frequent updates - Use notifications instead
  • Don’t use generic messages - “Error” tells nothing
  • Don’t ignore errors - Handle dialog.Show() errors
  • Don’t block unnecessarily - Consider async alternatives
  • Don’t use technical jargon - Plain language

Platform Differences

macOS

  • Sheet-style when attached to window
  • Standard keyboard shortcuts (⌘. for Cancel)
  • Follows system theme automatically
  • Accessibility built-in

Windows

  • Modal dialogs
  • TaskDialog appearance
  • Esc for Cancel
  • Follows system theme

Linux

  • GTK dialogs
  • Varies by desktop environment
  • Follows desktop theme
  • Standard keyboard navigation

Next Steps

File dialogs

Open, save, and folder selection.

Learn More →

Custom dialogs

Create custom dialog windows.

Learn More →

Notifications

Non-intrusive notifications.

Learn More →

Events

Use events for non-blocking communication.

Learn More →


Questions? Ask in Discord or check the dialog examples.

Edit page

Last updated: