Skip to content

Commit 8ff2463

Browse files
committed
Resolve dynamic border and outline colors against the view trait collection in Fabric
1 parent 8d23b14 commit 8ff2463

2 files changed

Lines changed: 61 additions & 9 deletions

File tree

‎packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -904,13 +904,21 @@ static void RCTAddContourEffectToLayer(
904904
[layer removeAllAnimations];
905905
}
906906

907-
static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(BorderColors borderColors)
907+
// CALayer colors are plain CGColors: converting a dynamic (PlatformColor /
908+
// DynamicColorIOS) UIColor without an explicit trait collection resolves against
909+
// UITraitCollection.currentTraitCollection, which tracks the system appearance
910+
// and ignores any overrideUserInterfaceStyle inherited by the view. Resolve
911+
// against the view's own trait collection instead, matching the backgroundColor
912+
// handling in invalidateLayer.
913+
static RCTBorderColors RCTCreateRCTBorderColorsFromBorderColors(
914+
BorderColors borderColors,
915+
UITraitCollection *traitCollection)
908916
{
909917
return RCTBorderColors{
910-
.top = RCTUIColorFromSharedColor(borderColors.top),
911-
.left = RCTUIColorFromSharedColor(borderColors.left),
912-
.bottom = RCTUIColorFromSharedColor(borderColors.bottom),
913-
.right = RCTUIColorFromSharedColor(borderColors.right)};
918+
.top = [RCTUIColorFromSharedColor(borderColors.top) resolvedColorWithTraitCollection:traitCollection],
919+
.left = [RCTUIColorFromSharedColor(borderColors.left) resolvedColorWithTraitCollection:traitCollection],
920+
.bottom = [RCTUIColorFromSharedColor(borderColors.bottom) resolvedColorWithTraitCollection:traitCollection],
921+
.right = [RCTUIColorFromSharedColor(borderColors.right) resolvedColorWithTraitCollection:traitCollection]};
914922
}
915923

916924
static CALayerCornerCurve CornerCurveFromBorderCurve(BorderCurve borderCurve)
@@ -1148,7 +1156,8 @@ - (void)invalidateLayer
11481156
_borderLayer = nil;
11491157

11501158
layer.borderWidth = (CGFloat)borderMetrics.borderWidths.left;
1151-
UIColor *borderColor = RCTUIColorFromSharedColor(borderMetrics.borderColors.left);
1159+
UIColor *borderColor = [RCTUIColorFromSharedColor(borderMetrics.borderColors.left)
1160+
resolvedColorWithTraitCollection:self.traitCollection];
11521161
layer.borderColor = borderColor.CGColor;
11531162
layer.cornerRadius = (CGFloat)borderMetrics.borderRadii.topLeft.horizontal;
11541163
layer.cornerCurve = CornerCurveFromBorderCurve(borderMetrics.borderCurves.topLeft);
@@ -1166,7 +1175,8 @@ - (void)invalidateLayer
11661175
layer.borderColor = nil;
11671176
layer.cornerRadius = 0;
11681177

1169-
RCTBorderColors borderColors = RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors);
1178+
RCTBorderColors borderColors =
1179+
RCTCreateRCTBorderColorsFromBorderColors(borderMetrics.borderColors, self.traitCollection);
11701180

11711181
RCTAddContourEffectToLayer(
11721182
_borderLayer,
@@ -1195,11 +1205,13 @@ - (void)invalidateLayer
11951205
// have to be drawn with Core Graphics, the same way non-solid borders are.
11961206
if (_props->outlineStyle == OutlineStyle::Solid && areBorderRadiiCircular(borderMetrics.borderRadii) &&
11971207
borderMetrics.borderRadii.topLeft.horizontal == 0) {
1198-
UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor);
1208+
UIColor *outlineColor =
1209+
[RCTUIColorFromSharedColor(_props->outlineColor) resolvedColorWithTraitCollection:self.traitCollection];
11991210
_outlineLayer.borderWidth = _props->outlineWidth;
12001211
_outlineLayer.borderColor = outlineColor.CGColor;
12011212
} else {
1202-
UIColor *outlineColor = RCTUIColorFromSharedColor(_props->outlineColor);
1213+
UIColor *outlineColor =
1214+
[RCTUIColorFromSharedColor(_props->outlineColor) resolvedColorWithTraitCollection:self.traitCollection];
12031215

12041216
RCTAddContourEffectToLayer(
12051217
_outlineLayer,

‎packages/react-native/React/Tests/Mounting/RCTViewComponentViewTests.mm‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -281,4 +281,44 @@ - (void)testSquareDottedAndDashedOutlinesAreDrawnWithCoreGraphics
281281
}
282282
}
283283

284+
#pragma mark - dynamic border and outline colors
285+
286+
- (void)testDynamicBorderAndOutlineColorsResolveAgainstViewTraitCollection
287+
{
288+
auto dynamicColor = SharedColor(Color(
289+
DynamicColor{
290+
.lightColor = static_cast<int32_t>(0xFFFF0000u),
291+
.darkColor = static_cast<int32_t>(0xFF00FF00u),
292+
}));
293+
UITraitCollection *lightTraits = [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight];
294+
295+
[lightTraits performAsCurrentTraitCollection:^{
296+
RCTViewComponentView *view = [RCTViewComponentView new];
297+
view.frame = CGRectMake(0, 0, 100, 100);
298+
view.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
299+
view.clipsToBounds = YES;
300+
301+
XCTAssertEqual([UITraitCollection currentTraitCollection].userInterfaceStyle, UIUserInterfaceStyleLight);
302+
XCTAssertEqual(view.traitCollection.userInterfaceStyle, UIUserInterfaceStyleDark);
303+
304+
auto props = std::make_shared<ViewProps>();
305+
props->yogaStyle.setBorder(facebook::yoga::Edge::All, facebook::yoga::StyleLength::points(4));
306+
props->borderColors.all = dynamicColor;
307+
props->borderStyles.all = BorderStyle::Solid;
308+
props->outlineWidth = 4;
309+
props->outlineColor = dynamicColor;
310+
props->outlineStyle = OutlineStyle::Solid;
311+
312+
[view updateProps:props oldProps:ViewShadowNode::defaultSharedProps()];
313+
[view finalizeUpdates:RNComponentViewUpdateMaskProps];
314+
315+
CALayer *outlineLayer = [view valueForKey:@"_outlineLayer"];
316+
XCTAssertNotNil(outlineLayer);
317+
XCTAssertNotNil((__bridge id)view.layer.borderColor);
318+
XCTAssertNotNil((__bridge id)outlineLayer.borderColor);
319+
XCTAssertTrue(CGColorEqualToColor(view.layer.borderColor, UIColor.greenColor.CGColor));
320+
XCTAssertTrue(CGColorEqualToColor(outlineLayer.borderColor, UIColor.greenColor.CGColor));
321+
}];
322+
}
323+
284324
@end

0 commit comments

Comments
 (0)