@@ -1040,10 +1040,20 @@ - (RCTUIView *)currentContainerView // [macOS]
10401040 if (_useCustomContainerView) {
10411041 if (!_containerView) {
10421042 _containerView = [[RCTPlatformView alloc ] initWithFrame: CGRectMake (0 , 0 , self .frame.size.width, self .frame.size.height)]; // [macOS]
1043+ #if TARGET_OS_OSX // [macOS
1044+ _containerView.wantsLayer = YES ;
1045+ #endif // macOS]
10431046 for (RCTPlatformView *subview in self.subviews ) { // [macOS]
10441047 [_containerView addSubview: subview];
10451048 }
1049+ #if !TARGET_OS_OSX // [macOS]
10461050 _containerView.clipsToBounds = self.clipsToBounds ;
1051+ #else // [macOS
1052+ // On macOS, clipsToBounds doesn't automatically set layer.masksToBounds
1053+ // like it does on iOS, so we need to set it directly.
1054+ _containerView.clipsToBounds = _props->getClipsContentToBounds ();
1055+ _containerView.layer .masksToBounds = _props->getClipsContentToBounds ();
1056+ #endif // macOS]
10471057 self.clipsToBounds = NO ;
10481058 _containerView.layer .mask = self.layer .mask ;
10491059 self.layer .mask = nil ;
@@ -1075,10 +1085,15 @@ - (void)invalidateLayer
10751085 }
10761086
10771087#if TARGET_OS_OSX // [macOS
1078- // clipsToBounds is stubbed out on macOS because it's not part of NSView.
1079- // Only set masksToBounds if there's no boxShadow - otherwise the shadow
1080- // sublayer (which extends beyond bounds) would be clipped.
1081- layer.masksToBounds = _props->boxShadow .empty () && self.clipsToBounds ;
1088+ // On macOS, clipsToBounds doesn't automatically set layer.masksToBounds like iOS does.
1089+ // When _useCustomContainerView is true (boxShadow + overflow:hidden), the container
1090+ // view handles clipping children while the main layer stays unclipped for the shadow.
1091+ // The container view's masksToBounds is set in currentContainerView getter.
1092+ if (_useCustomContainerView) {
1093+ layer.masksToBounds = NO ;
1094+ } else {
1095+ layer.masksToBounds = _props->getClipsContentToBounds ();
1096+ }
10821097#endif // macOS]
10831098
10841099 const auto borderMetrics = _props->resolveBorderMetrics (_layoutMetrics);
@@ -1337,7 +1352,8 @@ - (void)invalidateLayer
13371352 if (!_props->boxShadow .empty ()) {
13381353 _boxShadowLayer = [CALayer layer ];
13391354 [self .layer addSublayer: _boxShadowLayer];
1340- _boxShadowLayer.zPosition = _borderLayer.zPosition ;
1355+ // Box shadow should be behind all content but still visible
1356+ _boxShadowLayer.zPosition = BACKGROUND_COLOR_ZPOSITION - 1 ;
13411357 _boxShadowLayer.frame = RCTGetBoundingRect (_props->boxShadow , self.layer .bounds .size );
13421358
13431359 UIImage *boxShadowImage = RCTGetBoxShadowImage (
@@ -1351,8 +1367,11 @@ - (void)invalidateLayer
13511367#else // [macOS
13521368 // Keep a strong reference to the NSImage so that the CGImage it provides
13531369 // (via UIImageGetCGImageRef) remains valid while the layer uses it.
1370+ // The image is lazy - force it to render before extracting CGImage.
13541371 _boxShadowImage = boxShadowImage;
1355- _boxShadowLayer.contents = (__bridge id )UIImageGetCGImageRef (boxShadowImage);
1372+ [_boxShadowImage lockFocus ];
1373+ [_boxShadowImage unlockFocus ];
1374+ _boxShadowLayer.contents = (__bridge id )UIImageGetCGImageRef (_boxShadowImage);
13561375#endif // macOS]
13571376 }
13581377
0 commit comments