iced-cube

Overlays

Dialog

A modal window over a dimmed scrim, for a focused task or a confirmation.

use iced_cube::{alert_dialog, dialog};
use iced_cube::overlay::dialog::{self, Size};
API reference
Default: A trigger button opens the dialog. Escape, the close button or a click on the scrim dismisses it.Default: A trigger button opens the dialog. Escape, the close button or a click on the scrim dismisses it.
Static preview
Default. A trigger button opens the dialog. Escape, the close button or a click on the scrim dismisses it.

Usage

Wrap the root of your view in dialog, so the scrim covers the whole window. While the dialog is open, the content underneath still draws but gets no clicks, hover or key presses. It keeps its widget state, such as scroll positions, when the dialog opens and closes.

Use a dialog for a short task that needs attention before people go back to what they were doing. For a destructive confirmation, use alert_dialog: it has no close button and ignores clicks on the scrim, so the only ways out are Cancel, Escape or the destructive action. Enter does nothing in it by default, because a key press meant for something else should never delete anything; turn it on with .confirm_on_enter(true) when the action is easy to undo. Turn Escape off with .dismiss_on_escape(false) when even that is too easy.

Keyboard users answer an alert dialog with Tab: nothing is focused when it opens, the first Tab rings Cancel, the next rings the destructive action, and Enter or Space presses the ringed button. Shift+Tab goes back, and a click anywhere clears the ring. To confirm with a single chord instead, bind one to Action::Confirm in the keymap and turn on .confirm_on_enter(true).

The dialog handles its own keys, so it needs no subscription. When it opens, it focuses its first text field and unfocuses anything underneath. Tab and Shift+Tab then move between the text fields inside it and wrap at either end, so focus never leaves the dialog. It captures every key press its content leaves, so app-wide shortcuts from keys::subscription cannot change tabs, sliders or menus behind the scrim. Let a chosen shortcut through with .pass_through(...).

Menus, comboboxes and command lists inside a dialog get keys and clicks first. Escape or a click on the scrim closes an open menu or list and leaves the dialog open; the next one closes the dialog. The command palette example puts a command list in a dialog.

Some limits come from iced 0.14 itself:

  • Only text fields, text editors and an alert dialog’s own two buttons can take keyboard focus. Tab skips the buttons you pass to .action(...), so Space cannot press them. Set .on_confirm(...) so Enter runs the main action, or give a field an on_submit of its own.
  • A focused text field takes the first Escape to lose focus, so it takes a second Escape to dismiss the dialog.
  • There is no screen reader support, so the dialog’s title and description are not announced.

Examples

Form and keyboard

Fields inside a small dialog. Tab and Shift+Tab move focus between them through the default keymap, without leaving the dialog, and Enter saves through on_confirm.

Form and keyboard: Fields inside a small dialog. Tab and Shift+Tab move focus between them through the default keymap, without leaving the dialog, and Enter saves through on_confirm.Form and keyboard: Fields inside a small dialog. Tab and Shift+Tab move focus between them through the default keymap, without leaving the dialog, and Enter saves through on_confirm.
Static preview

Destructive confirmation

An alert dialog with Cancel and a destructive action. Enter confirms, Escape cancels and clicking the scrim does nothing.

Destructive confirmation: An alert dialog with Cancel and a destructive action. Enter confirms, Escape cancels and clicking the scrim does nothing.Destructive confirmation: An alert dialog with Cancel and a destructive action. Enter confirms, Escape cancels and clicking the scrim does nothing.
Static preview

API

ItemDescription
dialog(base)Wraps the content the dialog opens over. The dialog stays closed until .open(true).
.open(bool)Whether the dialog shows. Your app holds this value.
.title(text) / .description(text)The heading, and a line of muted text under it.
.body(element)Content between the header and the footer, such as a form.
.action(element)Adds a button to the footer, which lines them up on the right. Add the main action last.
.on_dismiss(message)Emitted by Escape, a click on the scrim and the close button. Without it the close button renders disabled.
.on_confirm(message)Emitted by Enter, through the keymap's Confirm action, usually the same message as the main footer action. Without it Enter does nothing. A field inside that submits on Enter keeps the key.
.dismiss_on_escape(bool) / .dismiss_on_scrim(bool)Turns either way of dismissing off. Both default to true.
.close_button(bool)Shows or hides the close button in the top right corner. Defaults to true.
.size(Size) / .width(pixels)The maximum width: Sm (384), Md (512, the default) or Lg (640). The dialog shrinks to fit smaller windows.
.keymap(Keymap<Action>)Replaces the default shortcuts.
.pass_through(chords)Chords the open dialog lets through to keys::subscription, such as the shortcut that toggles a command palette. Every other key press stops at the dialog.
.id(id)The surface's widget id, which scopes focus. Give nested dialogs different ids.
alert_dialog(base, title, description)A confirmation with Cancel and a destructive button. The scrim does not dismiss it and it has no close button.
.cancel(label) / .confirm(label)The button labels. They default to Cancel and Continue.
.on_cancel(message) / .on_confirm(message)Emitted by the buttons. Escape also cancels unless .dismiss_on_escape(false) is set.
.confirm_on_enter(bool)Whether Enter runs the destructive action while no button is focused. Defaults to false, so a stray Enter never destroys anything; keyboard users Tab to the button and press Enter or Space instead.
dialog::default_keymap()The default shortcuts as a Keymap<Action>. Bind, unbind or clear chords to change them.
action.effect(dismiss_on_escape)What a resolved Action does to an open dialog: Effect::Dismiss, Effect::Confirm or Effect::Focus(direction).
dialog::CLOSE_BUTTON_IDThe widget id of the close button, for clicking it in tests.
surface_style(tokens) / scrim_style(tokens)The surface and scrim styles, for reuse in custom overlays.

Keyboard

Default shortcuts. Every one can be changed or removed with a keymap; see Keyboard shortcuts.

KeysAction
EscapeClose Dismisses the dialog, unless Escape dismissal is turned off.
EnterConfirm Sends the dialog's confirm message. An alert dialog's destructive action only runs on Enter when it opts in.
TabFocusNext Focuses the next text field, or alert dialog button, wrapping from the last to the first.
Shift+TabFocusPrevious Focuses the previous text field, or alert dialog button, wrapping from the first to the last.
Esc