From 79101bc61bfb8d5270fdc673a10160716c7ba38b Mon Sep 17 00:00:00 2001 From: Motel Date: Thu, 28 May 2026 05:37:51 -0400 Subject: [PATCH] fix(ios): skip imageColor tint when New-Arch defaults it to 0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under React Native's New Architecture the codegen-generated MenuViewActionsSubactionsStruct declares `int imageColor{0}` as the default. The iOS bridge unconditionally forwards it, so the Swift unwrap `if let imageColor = details["imageColor"]` always succeeds — and `RCTConvert.uiColor(0)` returns a fully transparent UIColor. Result: every SF Symbol passed via `image` renders invisible on iOS 26 + New Arch. This guard checks the int value and skips the tint when it's the default (0). When the JS side explicitly passes imageColor: 0, the result is unchanged (transparent tint), so no observable regression for that case. Closes #1198. Refs #1034, #1002. --- ios/Shared/RCTMenuItem.swift | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/ios/Shared/RCTMenuItem.swift b/ios/Shared/RCTMenuItem.swift index bb6bb2b7..bc73700b 100644 --- a/ios/Shared/RCTMenuItem.swift +++ b/ios/Shared/RCTMenuItem.swift @@ -32,7 +32,14 @@ class RCTMenuAction { if self.image === nil { self.image = UIImage(named: image as String) } - if let imageColor = details["imageColor"] { + // Under React Native's New Architecture, the codegen-generated + // MenuViewActionsSubactionsStruct declares `int imageColor{0}` as + // the default, so the bridge always forwards a value even when JS + // didn't pass one. Without this guard the unwrap below would + // succeed with `imageColor == 0`, and `RCTConvert.uiColor(0)` + // returns a fully transparent UIColor — every SF Symbol passed + // via `image` would render invisible. Closes #1198, refs #1034 #1002. + if let imageColor = details["imageColor"], (imageColor as? Int) != 0 { self.image = self.image?.withTintColor(RCTConvert.uiColor(imageColor), renderingMode: .alwaysOriginal) } }