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, then
bridges the event synthetically to the logical ancestor chain outside the call site. UI
Toolkit's own native dispatch also reaches the target's PHYSICAL ancestors, but one that is
no logical ancestor of the call site runs none of its events: handlers for the event,
as the container of a React portal never sees it. 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 dispatch already covers it and
stops there rather than double-firing. A Button's click (ClickedBinding) and a
field's value change
(ChangeEventBinding<T>) cross the same way. 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.Appended)
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.
focusOrderPanelFocusOrderWhere the children sit in Tab order; by default after every element of the panel the tree is mounted on, as a portal into a document's body.
Returns
- PortalNode
The created PortalNode.
Exceptions
- ArgumentOutOfRangeException
layernames no member of UILayer, orfocusOrdernames no member of PanelFocusOrder.