From 7ca951794661dcae514ca591a27d5d5bcb5cfd19 Mon Sep 17 00:00:00 2001 From: andycall Date: Sun, 29 Mar 2026 11:01:19 -0700 Subject: [PATCH 1/2] fix(webf): narrow portal width fallback --- webf/lib/src/css/render_style.dart | 68 +++++++++++++++++++++++------- 1 file changed, 52 insertions(+), 16 deletions(-) diff --git a/webf/lib/src/css/render_style.dart b/webf/lib/src/css/render_style.dart index b3febb84da..1795481e61 100644 --- a/webf/lib/src/css/render_style.dart +++ b/webf/lib/src/css/render_style.dart @@ -3302,19 +3302,19 @@ class CSSRenderStyle extends RenderStyle !renderStyle.isSelfRenderReplaced() && renderStyle.position != CSSPositionType.absolute && renderStyle.position != CSSPositionType.fixed) { - if (parentStyle.isSelfRenderWidget()) { - RenderWidgetElementChild? childWrapper; - final RenderBoxModel? currentLayoutBox = - renderBoxModelInLayoutStack.isNotEmpty ? renderBoxModelInLayoutStack.last : null; - if (currentLayoutBox != null && identical(currentLayoutBox.renderStyle, renderStyle)) { - childWrapper = currentLayoutBox.findWidgetElementChild(); - } - childWrapper ??= target.attachedRenderer?.findWidgetElementChild(); - double? maxConstraintWidth; - try { - maxConstraintWidth = childWrapper?.effectiveChildConstraints.maxWidth; - } catch (_) {} + RenderWidgetElementChild? childWrapper; + final RenderBoxModel? currentLayoutBox = + renderBoxModelInLayoutStack.isNotEmpty ? renderBoxModelInLayoutStack.last : null; + if (currentLayoutBox != null && identical(currentLayoutBox.renderStyle, renderStyle)) { + childWrapper = currentLayoutBox.findWidgetElementChild(); + } + childWrapper ??= target.attachedRenderer?.findWidgetElementChild(); + double? maxConstraintWidth; + try { + maxConstraintWidth = childWrapper?.effectiveChildConstraints.maxWidth; + } catch (_) {} + if (parentStyle.isSelfRenderWidget()) { if (childWrapper != null && maxConstraintWidth != null && maxConstraintWidth.isFinite) { // Prefer the smaller (more restrictive) containing block width: // - Widget subtree constraints can differ from CSS logical width when an element @@ -3349,10 +3349,26 @@ class CSSRenderStyle extends RenderStyle // If there is no WebFWidgetElementChild (or no constraints yet), // fall through and let the parent (flex) constraints logic handle it. } else { - final RenderBoxModel? parentBox = parentStyle.attachedRenderBoxModel; - final BoxConstraints? pcc = parentBox?.contentConstraints; - if (pcc != null && pcc.hasBoundedWidth && pcc.maxWidth.isFinite) { - logicalWidth = pcc.maxWidth - renderStyle.margin.horizontal; + final RenderBoxModel? currentLayoutBoxForAncestor = + renderBoxModelInLayoutStack.isNotEmpty ? renderBoxModelInLayoutStack.last : null; + final bool parentIsAncestorInCurrentTree = currentLayoutBoxForAncestor == null + ? true + : isRenderSubtreeAncestor( + parentStyle.attachedRenderBoxModel, + currentLayoutBoxForAncestor, + ); + if (renderStyle.isSelfRenderWidget() && + !parentIsAncestorInCurrentTree && + childWrapper != null && + maxConstraintWidth != null && + maxConstraintWidth.isFinite) { + logicalWidth = maxConstraintWidth; + } else { + final RenderBoxModel? parentBox = parentStyle.attachedRenderBoxModel; + final BoxConstraints? pcc = parentBox?.contentConstraints; + if (pcc != null && pcc.hasBoundedWidth && pcc.maxWidth.isFinite) { + logicalWidth = pcc.maxWidth - renderStyle.margin.horizontal; + } } } @@ -3401,6 +3417,26 @@ class CSSRenderStyle extends RenderStyle } else { logicalWidth = maxConstraintWidth; } + } else if (renderStyle.isSelfRenderWidget() && + childWrapper != null && + maxConstraintWidth != null && + maxConstraintWidth.isFinite) { + final RenderBoxModel? currentLayoutBoxForAncestor = + renderBoxModelInLayoutStack.isNotEmpty ? renderBoxModelInLayoutStack.last : null; + final bool ancestorIsAncestorInCurrentTree = currentLayoutBoxForAncestor == null + ? true + : isRenderSubtreeAncestor( + ancestorRenderStyle.attachedRenderBoxModel, + currentLayoutBoxForAncestor, + ); + if (!ancestorIsAncestorInCurrentTree) { + // Only the portal-mounted WidgetElement root should ignore DOM + // ancestors from a detached render subtree. Regular descendants + // still resolve width from their active DOM containing block. + logicalWidth = maxConstraintWidth; + } else { + logicalWidth = ancestorRenderStyle.contentBoxLogicalWidth; + } } else { logicalWidth = ancestorRenderStyle.contentBoxLogicalWidth; } From 9acd5f2b8db3f623c1048333d60827e49f2e7668 Mon Sep 17 00:00:00 2001 From: andycall Date: Sun, 29 Mar 2026 11:03:44 -0700 Subject: [PATCH 2/2] fix(webf): avoid phantom flex scroll range --- webf/lib/src/rendering/flex.dart | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/webf/lib/src/rendering/flex.dart b/webf/lib/src/rendering/flex.dart index 3116012ed6..75fe65a220 100644 --- a/webf/lib/src/rendering/flex.dart +++ b/webf/lib/src/rendering/flex.dart @@ -7838,7 +7838,7 @@ class RenderFlexLayout extends RenderLayoutBox { Size childScrollableSize = _getChildSize(child)!; double childOffsetX = 0; double childOffsetY = 0; - double childTransformMainOverflow = 0; + double childTransformMainOffset = 0; if (child is RenderBoxModel) { final RenderStyle childRenderStyle = child.renderStyle; @@ -7875,12 +7875,9 @@ class RenderFlexLayout extends RenderLayoutBox { if (transformOffset != null) { childOffsetX += transformOffset.dx; childOffsetY += transformOffset.dy; - childTransformMainOverflow = math.max( - 0, - _isHorizontalFlexDirection - ? transformOffset.dx - : transformOffset.dy, - ); + childTransformMainOffset = _isHorizontalFlexDirection + ? transformOffset.dx + : transformOffset.dy; } } @@ -7892,8 +7889,8 @@ class RenderFlexLayout extends RenderLayoutBox { final double childCrossOffset = _isHorizontalFlexDirection ? childOffsetY : childOffsetX; final double childScrollableMainExtent = _isHorizontalFlexDirection - ? childScrollableSize.width + childTransformMainOverflow - : childScrollableSize.height + childTransformMainOverflow; + ? childScrollableSize.width + : childScrollableSize.height; final double childScrollableCrossExtent = _isHorizontalFlexDirection ? childScrollableSize.height + childOffsetY : childScrollableSize.width + childOffsetX; @@ -7915,11 +7912,13 @@ class RenderFlexLayout extends RenderLayoutBox { // instead of the pre-alignment stacked size. This prevents blank trailing // scroll range after children are shifted by negative leading space. final double childScrollableMain = math.max( - 0, - childMainPosition - physicalMainAxisStartBorder, - ) + - math.max(childBoxMainSize, childScrollableMainExtent) + - childPhysicalMainEndMargin; + 0, + childMainPosition - + physicalMainAxisStartBorder + + childTransformMainOffset + + math.max(childBoxMainSize, childScrollableMainExtent) + + childPhysicalMainEndMargin, + ); final double childScrollableCross = math.max( childBoxCrossSize + childCrossOffset, childScrollableCrossExtent);