Modal
Modal is the low-level modal component. It is responsible for only three things: drawing the mask, placing content, and providing the current input layer to the subtree while open. Confirm buttons, close keys, scrolling, and form submission are composed by you in the outer component or child components.

This recording is generated by docs/tapes/modal.tape. The example first moves a background list, then opens a modal. While the modal is open, pressing j only updates modal state; the background list does not keep moving. It then closes with Esc, opens again, and accepts the current task with Enter.
In the background state, press j/k to move and m to open the modal. Inside the modal, j/k are consumed by the modal, Enter accepts, Esc or c closes, and q quits.
Minimal form
Section titled “Minimal form”If child components inside the modal register their own EventScope::Current handlers, let Modal create the input layer itself:
Modal(open: false) does not render content and does not update its subtree. When opened, it creates a default blocks_lower=true layer and injects that layer into the subtree. SearchInput, Select, ScrollView, or custom use_event_handler(EventScope::Current, ...) calls inside the subtree naturally belong to the modal layer.
Handling modal keys in the parent
Section titled “Handling modal keys in the parent”When modal key logic lives in the parent component, have the parent own the layer and pass that same layer to Modal:
Do not split this pair apart. use_event_handler(EventScope::Layer(layer)) binds to the layer created by the parent; Modal(layer: Some(layer)) tells the modal to reuse that layer and inject it into the subtree. If you forget to pass layer, Modal creates another higher layer and the parent handler will not receive modal keys.
Input exclusivity
Section titled “Input exclusivity”blocks_lower defaults to the equivalent of Some(true), which fits real modal dialogs:
For non-blocking floating layers, temporary hints, or debug panels, pass blocks_lower: Some(false). That only means lower layers may still receive events; if an upper child component returns EventResult::Consumed, propagation still stops.
Modal itself does not decide which keys close the dialog for you. The low-level modal fits complex interaction. For ordinary confirmation, alerts, and shortcut help, prefer the built-in ConfirmModal, AlertModal, and ShortcutInfoModal.
Layout and mask
Section titled “Layout and mask”width and height decide the content region size, while placement decides where that content appears in the terminal:
style applies to the full-screen mask. The modal content style is decided by the subtree. A common pattern is putting a Border inside Modal: the outer Modal controls mask and placement, and the inner Border controls title, border, padding, and concrete layout.
When a modal needs long content, place ScrollView inside the Modal subtree. Its Current handler automatically belongs to the modal layer.