limn
    ↑↓ ChooseEnter OpenEsc Close
    GitHub

    Components/Overlays

    Modal / AlertDialog

    A centered surface over a dimmed window that takes the keyboard until it is answered. There are two types: Modal for a form or other content, and AlertDialog to confirm a consequential action.

    Native componentGuide source

    Preview

    CodeSource
    fn view(state: &State, palette: ComponentPalette) -> Element {
        let root = window_content(state, palette);
        Modal::new(
            root,
            state.creating,
            "New project",
            "The name can be changed later.",
            "create:close",
            palette,
        )
        .body(TextField::new("create:name", &state.name, "My project", palette).render())
        .footer(Button::new("create:confirm", "Create", palette).render())
        .initial_focus("create:name")
        .render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            match id.as_str() {
                "create:open" => state.creating = true,
                "create:close" => state.creating = false,
                "create:confirm" => state.create(),
                _ => {}
            }
        }
    }

    Modal / AlertDialog

    A centered surface over a dimmed window that takes the keyboard until it is answered. There are two types: Modal for a form or other content, and AlertDialog to confirm a consequential action.

    Import

    use limn::{AlertDialog, Component, Modal};

    Usage

    A dialog wraps the window’s root element, not the button that opens it: it covers the whole window, so it is built last, around everything else. It is controlled: pass whether it is open, and close it when it reports. While closed, render returns the root alone.

    fn view(state: &State, palette: ComponentPalette) -> Element {
        let root = window_content(state, palette);
        Modal::new(
            root,
            state.creating,
            "New project",
            "The name can be changed later.",
            "create:close",
            palette,
        )
        .body(TextField::new("create:name", &state.name, "My project", palette).render())
        .footer(Button::new("create:confirm", "Create", palette).render())
        .initial_focus("create:name")
        .render()
    }
    
    fn update(state: &mut State, action: &UiAction) {
        if let UiAction::Clicked { id } = action {
            match id.as_str() {
                "create:open" => state.creating = true,
                "create:close" => state.creating = false,
                "create:confirm" => state.create(),
                _ => {}
            }
        }
    }

    The button that reports create:open is an ordinary button anywhere in the window. To use several dialogs, wrap one in the next: the element one returns is the base of the other.

    Modal::new(base, open, title, description, close_id, palette) has a title row with a close button, the description when it is not empty, a body in a scroll area and a footer that stays in view.

    Modal::new(root, open, "Sources", "", "sources:close", palette)
        .width(Modal::fit_width(window_width, 420.0))
        .height(360.0)
        .body(form)
        .footer(actions)
        .backdrop_dismiss(true)
        .render()

    width is 520 unless set and never under 240. Modal::fit_width(viewport_width, max) is the width that keeps the window’s margin clear, and Modal::body_width(modal_width) the width a body can count on. height bounds the card, never under 160; the body takes what is left and scrolls. backdrop_dismiss(true) makes a click on the dimmed window report the close ID; without it that click does nothing. initial_focus(id) names the control focused when the modal opens and return_focus(id) the one focused when it closes.

    AlertDialog

    AlertDialog::new(base, open, title, description, confirm_id, cancel_id, palette) asks a question with a Cancel and a confirm button. The host goes ahead only when it receives confirm_id.

    AlertDialog::new(
        root,
        state.deleting,
        "Delete the project?",
        "This cannot be undone.",
        "delete:confirm",
        "delete:cancel",
        palette,
    )
    .confirm_label("Delete")
    .cancel_label("Cancel")
    .destructive(danger)
    .render()

    The labels are “Continue” and “Cancel” unless set, or the confirm and cancel of the library’s labels. destructive(color) fills the confirm button with that color. confirm_enabled(false) keeps the button in view and passive while the action is being prepared. alternative(id, label) adds a second way to go ahead between the two, and body(element) puts content between the description and the actions. width is 440 unless set; under 360 the actions stack. Cancel has the focus when the dialog opens, and a click on the dimmed window does not dismiss it.

    Keyboard

    KeyEffect
    TabMoves among the dialog’s controls and does not leave it.
    EscapeReports the close ID of a Modal, the cancel ID of an AlertDialog.

    When the dialog goes, focus returns to the control that had it.

    Motion

    The card fades in and settles 4 px into place, the dimmed backdrop fades with it, and both fade out; see Animation. animation_ms sets the entrance.

    Actions

    ActionWhen
    UiAction::Clicked { id } with a modal’s close IDIts close button, Escape, or the backdrop with backdrop_dismiss(true).
    UiAction::Clicked { id } with confirm_idThe confirm button.
    UiAction::Clicked { id } with cancel_idCancel, the close button or Escape.
    UiAction::Clicked { id } with the alternative’s IDThe alternative button.

    Controls the host puts in the body or the footer report their own actions.

    Accessibility

    A Modal is a dialog named by its title and described by its description, known as {close_id}:dialog. An AlertDialog is an alert dialog named and described the same way, known as {cancel_id}:dialog. The close button is a button named by labels().close, and a disabled DismissButton is still there, as disabled.

    API reference

    The guide covers composition, options and actions. Generate the complete Rust type and builder reference from the checkout:

    cargo doc -p limn --open

    Component API overview · State and actions

    The example is drawn by crates/limn-gallery/src/pages/overlays.rs.