Skip to main content

Portal

Portal is the low-level escape hatch for rendering a subtree in the global overlay stack instead of inline.

In ordinary layout, a child lives inside its parent's bounds and stacking context. A portal breaks that rule on purpose. It tells the runtime, "render this subtree in the overlay phase against the whole viewport." That is what makes modals, drawers, popovers, and toasts possible.

Most app authors should not start with Portal directly. Higher-level widgets such as Modal, Drawer, Popover, and Tooltip already handle the common overlay behavior and are easier to keep accessible and predictable.

Example

use fission::core::ui::{Container, Spacer, Text};
use fission::prelude::*;

let global_debug_overlay = if view.state.show_debug_banner {
Portal {
child: Container::new(Text::new("Diagnostics connected").into_node())
.padding_all(12.0)
.into_node(),
}
.build(ctx, view)
} else {
Spacer::default().into_node()
};

Your app state still decides whether the portal exists. The widget only changes where the child is composed.

Field table

FieldTypeMeaningNotes / default behavior
childNodeThe subtree to place in the overlay stack.Required. The portal itself returns an invisible spacer in normal layout.

Runtime boundary

Portal uses BuildCtx::register_portal(...) during build(). That means the overlay registration is explicit and visible to the runtime, not a hidden side effect after the frame has already been built.

The helper registers into the default portal layer. If you need modal, flyout, or toast ordering, use a higher-level widget or call BuildCtx::register_portal_with_layer(...) yourself inside a custom widget.

Specific advice

Use Portal when you are authoring your own overlay widget or application-wide overlay system. For normal product work, start with the more specific overlay widget that already matches the interaction. The more behavior you build directly on top of Portal, the more responsibility you take on for layering, dismissal, semantics, and testing.

Also remember that a portal changes rendering location, not state ownership. Keep open or closed flags, selected items, and form values in your app state as usual.

Modal, Drawer, Popover, Tooltip, and flyout.