Skip to content

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 text
await dialogs.Alert("Success", "Item saved successfully", "Got it");
ParameterTypeDefaultDescription
titlestring?Alert title. Pass null to omit.
messagestringAlert body text (required)
acceptTextstring"OK"Button text

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
}
ParameterTypeDefaultDescription
titlestring?Dialog title. Pass null to omit.
messagestringDialog body text (required)
acceptTextstring"Yes"Accept button text
cancelTextstring"No"Cancel button text

Display a text input dialog. Returns the entered text, or null if the user cancelled.

// Simple prompt
var name = await dialogs.Prompt("Name", "What is your name?");
if (name != null)
{
// user entered a value
}
// With all options
var pin = await dialogs.Prompt(
"Security",
"Enter your PIN",
acceptText: "Submit",
cancelText: "Cancel",
placeholder: "4-digit PIN",
initialValue: "",
maxLength: 4,
keyboard: Keyboard.Numeric
);
ParameterTypeDefaultDescription
titlestring?Dialog title. Pass null to omit.
messagestringDialog body text (required)
acceptTextstring"OK"Accept button text
cancelTextstring"Cancel"Cancel button text
placeholderstring?nullPlaceholder text shown when the input is empty
initialValuestring""Pre-filled input value
maxLengthint-1Maximum characters allowed (-1 = no limit)
keyboardKeyboard?nullKeyboard type (Keyboard.Numeric, Keyboard.Email, etc.)

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;
}
ParameterTypeDescription
titlestring?Sheet title. Pass null to omit.
cancelstring?Cancel button text. Pass null to omit.
destructionstring?Destructive action text (shown in red on some platforms). Pass null to omit.
buttonsstring[]Action button labels

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?"
);
}
}
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));
}
}
}
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;
}
}