Skip to content

Portals & deferred UI

Goal

Render into named slots (Portal / PortalMount), split narrow/main columns with SplitView, and mark lower-priority subtrees with DeferredFragment when Streamlit exposes st.fragment.

Portals

Read the contract in Phase 2 portals & prefetch. Portals let you gather children in one pass and mount them elsewhere in the shell (sidebar, dialog targets, etc.) while keeping a single StreamTree tree.

Deferred fragments

DeferredFragment wraps children in st.fragment when available so reruns can isolate expensive regions. Demo:

"""Deferred region via :class:`DeferredFragment` (``st.fragment`` when available).

Run: ``streamlit run examples/deferred_region_demo.py``

On Streamlit builds with ``st.fragment``, children render inside a fragment for
lower scheduling priority; otherwise they render inline like a normal subtree.
"""

from __future__ import annotations

from streamtree import component, render
from streamtree.core.element import Element
from streamtree.elements import DeferredFragment, Page, Text, VStack


@component
def DeferredRegionDemo() -> Element:
    heavy = tuple(Text(f"Row {i}") for i in range(12))
    return Page(
        VStack(
            Text("## DeferredFragment demo"),
            Text("Heavy block below is wrapped for fragment scheduling when supported."),
            DeferredFragment(*heavy),
        )
    )


if __name__ == "__main__":
    render(Page(DeferredRegionDemo()))

Composite layout stress test

phase2_composite_demo.py mixes Routes, ErrorBoundary, submit_many, and shell-friendly structure—use it as a “kitchen sink” reference when learning portals-adjacent patterns.

See also