日本語

Dialog

A modal dialog, a sheet along an edge of the viewport, and an alert dialog that asks the visitor to confirm.

Result

dialog.rs
use hypersig::html::{div, p};
use hypersig::style::pattern::{stack, wrap};
use hypersig::style::value::rem;
use hypersig::{Page, Signals};
use hypersig_ui::{ButtonSize, ButtonVariant, Dialog, Side, TextField, dialog_footer};
use serde::{Deserialize, Serialize};

#[derive(Signals, Serialize, Deserialize)]
pub struct Project {
    name: String,
    status: String,
}

const RENAME: Dialog<Project> = Dialog::new("rename");
const DELETE: Dialog<Project> = Dialog::new("delete");
const DETAILS: Dialog<Project> = Dialog::new("details");

pub fn page() -> Page<Project> {
    let name = Project::name();
    let status = Project::status();
    let initial = Project {
        name: "hypersig".into(),
        status: String::new(),
    };
    Page::new(
        "Project",
        initial,
    )
    .child(
        div()
            .css(stack(rem(1)))
            .child(
                div()
                    .css(wrap(rem(0.5)))
                    .child(
                        RENAME
                            .trigger(ButtonVariant::Outline, ButtonSize::Default)
                            .text("Rename"),
                    )
                    .child(
                        DETAILS
                            .trigger(ButtonVariant::Outline, ButtonSize::Default)
                            .text("Details"),
                    )
                    .child(
                        DELETE
                            .trigger(ButtonVariant::Destructive, ButtonSize::Default)
                            .text("Delete"),
                    ),
            )
            .child(p().attr("role", "status").bind_text(status))
            .child(
                RENAME.dialog(
                    "Rename project",
                    "The new name shows everywhere the project appears.",
                    div()
                        .css(stack(rem(1)))
                        .child(TextField::new(
                            "Name",
                            name,
                        ))
                        .child(
                            dialog_footer()
                                .child(
                                    RENAME
                                        .close(ButtonVariant::Outline, ButtonSize::Default)
                                        .text("Cancel"),
                                )
                                .child(
                                    RENAME
                                        .close(ButtonVariant::Default, ButtonSize::Default)
                                        .on_click(status.set("Renamed the project."))
                                        .text("Save"),
                                ),
                        ),
                ),
            )
            .child(
                DETAILS.sheet(
                    Side::Right,
                    "Project details",
                    "Created on March 3. Deployed 12 times.",
                    dialog_footer().child(
                        DETAILS
                            .close(ButtonVariant::Outline, ButtonSize::Default)
                            .text("Done"),
                    ),
                ),
            )
            .child(
                DELETE.alert_dialog(

                    "Delete this project?",
                    "The project and its deployments are removed. This cannot be undone.",
                    dialog_footer()
                        .child(
                            DELETE
                                .close(ButtonVariant::Outline, ButtonSize::Default)
                                .text("Cancel"),
                        )
                        .child(
                            DELETE
                                .close(ButtonVariant::Destructive, ButtonSize::Default)
                                .on_click(status.set("Deleted the project."))
                                .text("Delete"),
                        ),
                ),
            ),
    )
}

Accessibility

Declare the dialog as a const and use it for the dialog and for the buttons that open and close it. The buttons carry commandfor and command, and the browser opens the <dialog> with showModal(). While it is open, the rest of the page is inert, Escape closes the dialog, and on closing, focus returns to the button that opened it. Invoker commands are available from Chrome 135, Firefox 144, and Safari 26.2.

The dialog is labeled by its title and described by its description through ids derived from the name. An alert dialog has role="alertdialog" and no close button in its corner, so the visitor answers with one of its buttons.

A sheet is the same modal <dialog>, placed along one edge of the viewport by Dialog::sheet, so it keeps the focus, Escape, and backdrop behavior of a dialog.

KeyWhat it does
TabMoves between the dialog's controls and never reaches the page behind.
EscapeCloses the dialog and returns focus to the button that opened it.

API

ItemSummary
Dialog::newA dialog whose id is name.
triggerA button that opens the dialog.
openA statement that opens the dialog, as its trigger button does.
dismissA statement that closes the dialog, as its close button does.
closeA button that closes the dialog. Put it inside the dialog.
dialogThe dialog, with title, description, content, and a close button in its corner.
alert_dialogAn alert dialog, which asks the visitor to confirm or cancel before going on.
sheetA sheet: a dialog along the side edge of the viewport.
SideThe edge of the viewport a Dialog::sheet sits along.
dialog_footerThe row of buttons at the bottom of a dialog, aligned to the end.