Skip to content

Commit 982ab4a

Browse files
feat(ios): add backgroundColor prop to top bar buttons
Add a new `backgroundColor` option to `OptionsTopBarButton` that sets a solid color on the iOS 26 Liquid Glass circular platter behind React component bar buttons. Native implementation: - Parse `backgroundColor` in RNNButtonOptions (init/copy/merge) - Pass the resolved UIColor from RNNButtonBuilder to RNNReactButtonView.buttonBackgroundColor - syncButtonBackground targets the _UINavigationBarPlatter- SubviewContainerView (self.superview³) and applies the color, cornerRadius, and clipsToBounds to keep it circular - Called from both didMoveToWindow (early, prevents flash on push) and layoutSubviews (handles re-layouts) - When buttonBackgroundColor is nil the platter resets to clearColor, preventing color leaking between buttons during navigation transitions Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 340487d commit 982ab4a

6 files changed

Lines changed: 31 additions & 0 deletions

File tree

ios/RNNButtonBuilder.mm

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ - (RNNUIBarButtonItem *)build:(RNNButtonOptions *)button
3030
parentComponentId:parentComponentId
3131
componentType:RNNComponentTypeTopBarButton
3232
reactViewReadyBlock:nil];
33+
view.buttonBackgroundColor = [button.backgroundColor withDefault:nil];
3334
return [[RNNUIBarButtonItem alloc] initWithCustomView:view
3435
buttonOptions:button
3536
onPress:onPress];

ios/RNNButtonOptions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
@property(nonatomic, strong) RNNIconBackgroundOptions *iconBackground;
2525
@property(nonatomic, strong) Bool *disableIconTint;
2626
@property(nonatomic, strong) Bool *hideSharedBackground;
27+
@property(nonatomic, strong) Color *backgroundColor;
2728

2829
- (RNNButtonOptions *)withDefault:(RNNButtonOptions *)defaultOptions;
2930

ios/RNNButtonOptions.mm

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ - (instancetype)initWithDict:(NSDictionary *)dict {
2626
self.systemItem = [TextParser parse:dict key:@"systemItem"];
2727
self.disableIconTint = [BoolParser parse:dict key:@"disableIconTint"];
2828
self.hideSharedBackground = [BoolParser parse:dict key:@"hideSharedBackground"];
29+
self.backgroundColor = [ColorParser parse:dict key:@"backgroundColor"];
2930

3031
return self;
3132
}
@@ -51,6 +52,7 @@ - (RNNButtonOptions *)copy {
5152
newOptions.systemItem = self.systemItem.copy;
5253
newOptions.disableIconTint = self.disableIconTint.copy;
5354
newOptions.hideSharedBackground = self.hideSharedBackground.copy;
55+
newOptions.backgroundColor = self.backgroundColor.copy;
5456
return newOptions;
5557
}
5658

@@ -92,6 +94,8 @@ - (void)mergeOptions:(RNNButtonOptions *)options {
9294
self.disableIconTint = options.disableIconTint;
9395
if (options.hideSharedBackground.hasValue)
9496
self.hideSharedBackground = options.hideSharedBackground;
97+
if (options.backgroundColor.hasValue)
98+
self.backgroundColor = options.backgroundColor;
9599
}
96100

97101
- (BOOL)shouldCreateCustomView {

ios/RNNReactButtonView.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@
66

77
@interface RNNReactButtonView : RNNComponentView
88

9+
@property(nonatomic, strong) UIColor *buttonBackgroundColor;
10+
911
@end

ios/RNNReactButtonView.mm

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@ - (void)updateConstraintsToFitSize {
4343
}
4444
}
4545

46+
- (void)didMoveToWindow {
47+
[super didMoveToWindow];
48+
if (self.window) {
49+
[self syncButtonBackground];
50+
}
51+
}
52+
4653
- (void)layoutSubviews {
4754
[super layoutSubviews];
4855
if (!_didCenter && self.superview && self.frame.size.width > 0) {
@@ -54,6 +61,16 @@ - (void)layoutSubviews {
5461
self.layer.affineTransform = CGAffineTransformMakeTranslation(tx, 0);
5562
}
5663
}
64+
[self syncButtonBackground];
65+
}
66+
67+
- (void)syncButtonBackground {
68+
UIView *target = self.superview.superview.superview;
69+
if (!target || target.bounds.size.height <= 0) return;
70+
71+
target.backgroundColor = _buttonBackgroundColor ?: [UIColor clearColor];
72+
target.layer.cornerRadius = target.bounds.size.height / 2.0;
73+
target.clipsToBounds = YES;
5774
}
5875

5976
- (NSString *)componentType {

src/interfaces/Options.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,12 @@ export interface OptionsTopBarButton {
658658
* @see {@link https://developer.android.com/guide/topics/resources/menu-resource|Android developer guide: Menu resource}
659659
*/
660660
showAsAction?: 'ifRoom' | 'withText' | 'always' | 'never';
661+
/**
662+
* (iOS 26+ only) Set a solid background color on the circular Liquid Glass
663+
* platter behind the button. When nil the platter is reset to clear.
664+
* #### (iOS specific)
665+
*/
666+
backgroundColor?: Color;
661667
}
662668

663669
export interface OptionsSearchBar {

0 commit comments

Comments
 (0)