Modal¶
An overlay container for dialogs and focused interactions.
Usage¶
ui.layers([
MainContent(),
state.showModal &&
ui.modal({
id: "confirm",
title: "Confirm Action",
content: ui.text("Are you sure?"),
actions: [
ui.button({ id: "yes", label: "Yes" }),
ui.button({ id: "no", label: "No" }),
],
onClose: () => app.update((s) => ({ ...s, showModal: false })),
}),
])
Props¶
| Prop | Type | Default | Description |
|---|---|---|---|
id |
string |
required | Unique identifier |
title |
string |
- | Optional modal header title |
content |
VNode |
required | Main modal body |
actions |
VNode[] |
[] |
Action row (typically buttons) |
width |
number \| "auto" |
"auto" |
Preferred modal width |
maxWidth |
number |
- | Maximum width constraint |
backdrop |
"none" \| "dim" \| "opaque" |
"dim" |
Backdrop style |
closeOnBackdrop |
boolean |
true |
Close when clicking backdrop |
closeOnEscape |
boolean |
true |
Close on Esc |
onClose |
() => void |
- | Callback when modal requests close |
initialFocus |
string |
- | ID to focus when modal opens |
returnFocusTo |
string |
- | ID to restore focus on close |
Examples¶
Confirmation dialog with explicit focus target¶
ui.modal({
id: "delete-confirm",
title: "Delete item?",
content: ui.text("This action cannot be undone."),
actions: [
ui.button({ id: "cancel", label: "Cancel" }),
ui.button({ id: "confirm", label: "Delete" }),
],
initialFocus: "cancel",
returnFocusTo: "open-delete-modal",
onClose: () => app.update((s) => ({ ...s, showDeleteModal: false })),
})
Notes¶
- Modals are rendered by conditionally including them in the tree (there is no
openprop). - Render modals inside
ui.layers(...)so they stack above base content.
Related¶
- Layers - Overlay stacking container
- Layer - Generic layer primitive
- Focus Trap - Keep keyboard focus inside overlays