Portals
Need a dialog or anchored menu? Use Modal / Popup — they ship native <dialog> / popover with focus restore. portal() only moves DOM nodes (toasts, custom shells).
LIVE
<Modal> (prefer over portal())
Prefer Modal / Popup
view! {
<Modal id="confirm">
<button slot="trigger" type="button">"Open"</button>
<p>"Focus-trapped dialog"</p>
</Modal>
}Portal target
Add a target element in your layout shell:
view! {
<>
<main><Slot /></main>
<div id="modal-root" data-r-portal-target="modal"></div>
</>
}Portal content
#[component]
fn Modal(open: bool, children: Vec<Child>) -> View {
if !open {
return view! { <></> };
}
portal("modal", children)
}
view! {
<Modal open={show_modal.get()}>
<div class="modal-backdrop">
<div class="modal">"Dialog content"</div>
</div>
</Modal>
}data-r-portal
SSR emits a <template data-r-portal="modal">. After resume, the runtime moves children into the matching data-r-portal-target element.