From 3f025de4e25cf33df0d41b73995219c3469fe561 Mon Sep 17 00:00:00 2001 From: Jacques Leupin Date: Wed, 5 Aug 2026 12:50:27 -0700 Subject: [PATCH] Resolve dynamic border and outline colors against the view trait collection in Fabric --- .../View/RCTViewComponentView.mm | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm index 92c0bb8b4e6..1096c76bd4e 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm @@ -913,13 +913,21 @@ static void RCTAddContourEffectToLayer( [layer removeAllAnimations]; } -static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(BorderColors borderColors) +// CALayer colors are plain CGColors: converting a dynamic (PlatformColor / +// DynamicColorIOS) UIColor without an explicit trait collection resolves against +// UITraitCollection.currentTraitCollection, which tracks the system appearance +// and ignores any overrideUserInterfaceStyle inherited by the view. Resolve +// against the view's own trait collection instead, matching the backgroundColor +// handling in invalidateLayer. +static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors( + BorderColors borderColors, + UITraitCollection *traitCollection) { return RCTBorderColors{ - .top = RCTUIColorFromSharedColor(borderColors.top), - .left = RCTUIColorFromSharedColor(borderColors.left), - .bottom = RCTUIColorFromSharedColor(borderColors.bottom), - .right = RCTUIColorFromSharedColor(borderColors.right)}; + .top = [RCTUIColorFromSharedColor(borderColors.top) resolvedColorWithTraitCollection:traitCollection], + .left = [RCTUIColorFromSharedColor(borderColors.left) resolvedColorWithTraitCollection:traitCollection], + .bottom = [RCTUIColorFromSharedColor(borderColors.bottom) resolvedColorWithTraitCollection:traitCollection], + .right = [RCTUIColorFromSharedColor(borderColors.right) resolvedColorWithTraitCollection:traitCollection]}; } static CALayerCornerCurve CornerCurveFromBorderCurve(BorderCurve borderCurve) @@ -1157,7 +1165,8 @@ - (void)invalidateLayer _borderLayer = nil; layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left; - UIColor *borderColor = RCTUIColorFromSharedColor(borderMetrics.borderColors.left); + UIColor *borderColor = [RCTUIColorFromSharedColor(borderMetrics.borderColors.left) + resolvedColorWithTraitCollection:self.traitCollection]; layer.borderColor = borderColor.CGColor; layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft.horizontal; layer.cornerCurve = CornerCurveFromBorderCurve(borderMetrics.borderCurves.topLeft); @@ -1175,7 +1184,8 @@ - (void)invalidateLayer layer.borderColor = nil; layer.cornerRadius = 0; - RCTBorderColors borderColors = RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors); + RCTBorderColors borderColors = + RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors, self.traitCollection); RCTAddContourEffectToLayer( _borderLayer, @@ -1201,11 +1211,13 @@ - (void)invalidateLayer layer.bounds, -_props->outlineOffset - _props->outlineWidth, -_props->outlineOffset - _props->outlineWidth); if (areBorderRadiiCircular(borderMetrics.borderRadii) && borderMetrics.borderRadii.topLeft.horizontal == 0) { - UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor); + UIColor *outlineColor = [RCTUIColorFromSharedColor(_props->outlineColor) + resolvedColorWithTraitCollection:self.traitCollection]; _outlineLayer.borderWidth = _props->outlineWidth; _outlineLayer.borderColor = outlineColor.CGColor; } else { - UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor); + UIColor *outlineColor = [RCTUIColorFromSharedColor(_props->outlineColor) + resolvedColorWithTraitCollection:self.traitCollection]; RCTAddContourEffectToLayer( _outlineLayer,