Table of Contents

Method Portal

Namespace
Velvet
Assembly
Velvet.Docs.dll

Portal(string, VNode?[]?, string?)

Renders children into the Portal target identified by targetId, detaching them from the surrounding DOM position so they mount under a different host element. targetId must reference an ID previously registered via FiberPortalRegistry.Register.

public static PortalNode Portal(string targetId, VNode?[]? children = null, string? key = null)

Parameters

targetId string

Portal target ID registered via FiberPortalRegistry.Register.

children VNode[]

Descendant VNodes mounted into the resolved portal target.

key string

Key used to disambiguate siblings at the same position.

Returns

PortalNode

The created PortalNode.

Remarks

Context inheritance and event bubbling both follow the LOGICAL tree. Children inherit the context enclosing the V.Portal call site, and an events: handler on a logical ancestor of the call site also fires for a pointer / key / focus event raised on a portal child: Velvet physically reparents the children under the registered target element (so UI Toolkit's own native dispatch bubbles them up the target's PHYSICAL ancestor chain too), then separately bridges the event synthetically to the logical ancestor chain outside the call site. An element that happens to sit on BOTH chains — a physical ancestor of the target AND a logical ancestor of the call site — still fires exactly once: the synthetic walk detects that native bubbling already covers it and stops there rather than double-firing. Button's native click (ClickedBinding) and field value-change (ChangeEventBinding<T>) stay physical-tree-only in every portal form — neither has an underlying bubbling event object to carry across a logical boundary. See the portals documentation for the full contract.

Portal(VisualElement, VNode?[]?, string?)

Renders children into target — a container the caller already holds, rather than one published under a name. The React form: createPortal(children, container) takes the node itself, so two trees in one process cannot collide the way two registrations of one id do, and an element reached through a refCallback is a valid container without being named first.

public static PortalNode Portal(VisualElement target, VNode?[]? children = null, string? key = null)

Parameters

target VisualElement

Container the children attach to. Null renders nothing and warns.

children VNode[]

Nodes to render at the target.

key string

Key used to disambiguate siblings at the same position.

Returns

PortalNode

The created PortalNode.

Remarks

Passing a different container on a later render moves the children: the reconciler cannot patch one container's portal into another's, so the old unmounts and the new mounts. A registry target behaves differently — its id resolves once at mount and is then held, so re-registering the id points only future portals elsewhere. The portals documentation states that difference; the rest of the contract (context inheritance, event bubbling) is the same as the Portal(string, VNode?[]?, string?) form.

Portal(UILayer, VNode?[]?, string?, PanelFocusOrder)

Renders children into a framework-managed screen-space layer panel sorted around the app's main panel — one host panel per layer per reconciler, created lazily and destroyed with the reconciler. Like every portal, the children stay part of the LOGICAL tree: context and state cross the boundary, and an events: handler on a logical ancestor of the call site also fires for a pointer / key / focus event raised on a child, bridged synthetically across the separate host Panel. Relational group-/peer- variants and focus-within do NOT cross (they register their own native callbacks directly, bypassing the bridge), and responsive breakpoints evaluate against the layer panel's own width. Screen-space layers always composite over the 3D scene; UI that must sit among scene geometry is WorldSpace(Vector3, Quaternion?, Vector2?, VNode?[]?, string?, PanelFocusOrder)'s territory.

public static PortalNode Portal(UILayer layer, VNode?[]? children = null, string? key = null, PanelFocusOrder focusOrder = PanelFocusOrder.Isolated)

Parameters

layer UILayer

The framework-managed layer panel to attach the children to.

children VNode[]

Descendant VNodes mounted into the layer panel.

key string

Key used to disambiguate siblings at the same position.

focusOrder PanelFocusOrder

Returns

PortalNode

The created PortalNode.

Exceptions

ArgumentOutOfRangeException

layer names no member of UILayer, or focusOrder names no member of PanelFocusOrder.