Dialog
A modal dialog, a sheet along an edge of the viewport, and an alert dialog that asks the visitor to confirm.
Result
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.
| Key | What it does |
|---|---|
| Tab | Moves between the dialog's controls and never reaches the page behind. |
| Escape | Closes the dialog and returns focus to the button that opened it. |
API
| Item | Summary |
|---|---|
Dialog::new | A dialog whose id is name. |
trigger | A button that opens the dialog. |
open | A statement that opens the dialog, as its trigger button does. |
dismiss | A statement that closes the dialog, as its close button does. |
close | A button that closes the dialog. Put it inside the dialog. |
dialog | The dialog, with title, description, content, and a close button in its corner. |
alert_dialog | An alert dialog, which asks the visitor to confirm or cancel before going on. |
sheet | A sheet: a dialog along the side edge of the viewport. |
Side | The edge of the viewport a Dialog::sheet sits along. |
dialog_footer | The row of buttons at the bottom of a dialog, aligned to the end. |