Shell | Dialogs
All user-facing dialogs in Shiny Shell go through the IDialogs interface. Inject it into your ViewModels via constructor injection.
public class MyViewModel(IDialogs dialogs){ // dialogs is ready to use}IDialogs is registered as a singleton by UseShinyShell() and dispatches all calls to the UI thread automatically — safe to call from any thread.
Display an informational dialog with a single button.
await dialogs.Alert("Error", "Something went wrong");
// With custom button textawait dialogs.Alert("Success", "Item saved successfully", "Got it");| Parameter | Type | Default | Description |
|---|---|---|---|
title | string? | — | Alert title. Pass null to omit. |
message | string | — | Alert body text (required) |
acceptText | string | "OK" | Button text |
Confirm
Section titled “Confirm”Display a confirmation dialog and return the user’s choice.
bool confirmed = await dialogs.Confirm( "Delete Item", "Are you sure you want to delete this?", "Delete", "Cancel");
if (confirmed){ // proceed with deletion}| Parameter | Type | Default | Description |
|---|---|---|---|
title | string? | — | Dialog title. Pass null to omit. |
message | string | — | Dialog body text (required) |
acceptText | string | "Yes" | Accept button text |
cancelText | string | "No" | Cancel button text |
Prompt
Section titled “Prompt”Display a text input dialog. Returns the entered text, or null if the user cancelled.
// Simple promptvar name = await dialogs.Prompt("Name", "What is your name?");if (name != null){ // user entered a value}
// With all optionsvar pin = await dialogs.Prompt( "Security", "Enter your PIN", acceptText: "Submit", cancelText: "Cancel", placeholder: "4-digit PIN", initialValue: "", maxLength: 4, keyboard: Keyboard.Numeric);| Parameter | Type | Default | Description |
|---|---|---|---|
title | string? | — | Dialog title. Pass null to omit. |
message | string | — | Dialog body text (required) |
acceptText | string | "OK" | Accept button text |
cancelText | string | "Cancel" | Cancel button text |
placeholder | string? | null | Placeholder text shown when the input is empty |
initialValue | string | "" | Pre-filled input value |
maxLength | int | -1 | Maximum characters allowed (-1 = no limit) |
keyboard | Keyboard? | null | Keyboard type (Keyboard.Numeric, Keyboard.Email, etc.) |
ActionSheet
Section titled “ActionSheet”Display an action sheet with multiple options. Returns the text of the selected button.
var action = await dialogs.ActionSheet( "Photo Options", "Cancel", "Delete Photo", "Take Photo", "Choose from Library", "Share");
switch (action){ case "Take Photo": // open camera break; case "Choose from Library": // open gallery break; case "Share": // share photo break; case "Delete Photo": // destructive action break;}| Parameter | Type | Description |
|---|---|---|
title | string? | Sheet title. Pass null to omit. |
cancel | string? | Cancel button text. Pass null to omit. |
destruction | string? | Destructive action text (shown in red on some platforms). Pass null to omit. |
buttons | string[] | Action button labels |
Common Patterns
Section titled “Common Patterns”Navigation Confirmation
Section titled “Navigation Confirmation”Use IDialogs with INavigationConfirmation to guard unsaved changes:
public class EditViewModel(INavigator navigator, IDialogs dialogs) : INavigationConfirmation{ public bool HasUnsavedChanges { get; set; }
public async Task<bool> CanNavigate() { if (!HasUnsavedChanges) return true;
return await dialogs.Confirm( "Unsaved Changes", "You have unsaved changes. Discard them?" ); }}Delete Confirmation
Section titled “Delete Confirmation”public class ItemViewModel(INavigator navigator, IDialogs dialogs){ async Task DeleteItem() { if (await dialogs.Confirm("Delete", "This action cannot be undone.")) { await itemService.Delete(ItemId); await navigator.GoBack(("Deleted", true)); } }}User Input
Section titled “User Input”public class ListViewModel(IDialogs dialogs){ async Task RenameItem(Item item) { var newName = await dialogs.Prompt( "Rename", "Enter a new name", placeholder: "New name", initialValue: item.Name, maxLength: 100 );
if (newName != null) item.Name = newName; }}