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
targetIdstringPortal target ID registered via
FiberPortalRegistry.Register.childrenVNode[]Descendant VNodes mounted into the resolved portal target.
keystringKey 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
targetVisualElementContainer the children attach to. Null renders nothing and warns.
childrenVNode[]Nodes to render at the target.
keystringKey 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
layerUILayerThe framework-managed layer panel to attach the children to.
childrenVNode[]Descendant VNodes mounted into the layer panel.
keystringKey used to disambiguate siblings at the same position.
focusOrderPanelFocusOrder
Returns
- PortalNode
The created PortalNode.
Exceptions
- ArgumentOutOfRangeException
layernames no member of UILayer, orfocusOrdernames no member of PanelFocusOrder.