react-native-screens icon indicating copy to clipboard operation
react-native-screens copied to clipboard

feat(iOS): support UIBarButtonItem in header

Open johankasperi opened this issue 6 months ago • 1 comments

Description

The current implementation of headerLeft and headerRight adds a react view as a custom view in a UIBarButtonItem. This implementation is sufficient at most times but I believe we can achieve greater "native feel" if the native stack has an protocol for adding actual UIBarButtonItems in the header. As the UIBarButtonItems has properties and features that can be difficult to mimic with a react view.

Also with the introduction of iOS 26, using only custom views in UIBarButtonItem presents some limitations. Mainly that the adaptive tint color (based on the underlying view) is not working on a UIBarButtonItem with a custom view as demonstrated below under "Screenshots".

Changes

This PR adds the properties headerRightBarButtonItems and headerLeftBarButtonsItems on the native stack Screen that makes it possible to add one or several UIBarButtonItem to the right/left of the header. Most of the features of the UIBarButtonItem is supported (see either "Bar Button Items" in the example apps or the type definition).

Screenshots / GIFs

Non adaptive tint color when using old property headerRight on iOS 26

https://github.com/user-attachments/assets/194c70b5-7492-48df-aa2c-8fb889ece461

Adaptive tint color when using new property headerRightBarButtonItems on iOS 26

https://github.com/user-attachments/assets/9acb1981-3461-4f28-8a0d-54ea9956d3c0

UIBarButtonItem with style "prominent" on iOS 26

Simulator Screenshot - iPhone 16 Pro - 2025-06-27 at 16 28 39

UIBarButtonItem with UIMenu on iOS 26

https://github.com/user-attachments/assets/db2f7bab-3ade-423f-b80b-9c35b6cee578

Test code and steps to reproduce

I've created a screen named "Bar Button Items" in the example app that showcases all of the proposed features.

Checklist

  • [x] Included code example that can be used to test this change
  • [x] Updated TS types
  • [ ] Updated documentation:
    • [ ] https://github.com/software-mansion/react-native-screens/blob/main/guides/GUIDE_FOR_LIBRARY_AUTHORS.md
    • [ ] https://github.com/software-mansion/react-native-screens/blob/main/native-stack/README.md
    • [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/types.tsx
    • [ ] https://github.com/software-mansion/react-native-screens/blob/main/src/native-stack/types.tsx Unsure if I need to do this. I'm targeting react-navigation v6 and above so no JS changes has been made to react-native-screens in this PR. Would appreciate some guidance to if and where I should make documentation changes if needed. Thank you!
  • [ ] Ensured that CI passes

johankasperi avatar Jun 27 '25 15:06 johankasperi

Related PR in react-navigation: https://github.com/react-navigation/react-navigation/pull/12657

johankasperi avatar Jun 27 '25 16:06 johankasperi

i like this

Pnlvfx avatar Jul 02 '25 22:07 Pnlvfx

Hey! This is really promising. We're working currently on support for iOS 26 etc. and we're doing general overhaul of the lib. As of now, we're not sure what will be the API shape & scope, therefore I won't review it for now. Once we settle the internal discussion I'll revisit your implementation. I'm sure we'll be able to land it in some form.

kkafar avatar Jul 18 '25 13:07 kkafar

Hey! This is really promising. We're working currently on support for iOS 26 etc. and we're doing general overhaul of the lib. As of now, we're not sure what will be the API shape & scope, therefore I won't review it for now. Once we settle the internal discussion I'll revisit your implementation. I'm sure we'll be able to land it in some form.

I'm really glad you liked it! Yeah I saw that you have done a bunch of iOS 26 related PRs and changes to the API so I understand that my suggestion may not match the shape you are targeting. Please let me know if there are any changes I can do right now and I will happily do them asap. I truly believe something like this would be awesome for react-native-screens when iOS 26 is out of beta.

johankasperi avatar Aug 04 '25 12:08 johankasperi

Hi Great stuff. We're looking at your PR and would like to merge the changes soon. Here are some comments from me, and I believe @kkafar wants to look more closely in the following days.

Also, please update the PR with changes from main branch. There could be some conflicts.

Thank you! I've updated the PR with changes from main and resolved all conflicts

johankasperi avatar Aug 06 '25 12:08 johankasperi

Hey, I most likely won't find time tomorrow & I'm going for a two week PTO on Thursday. I'll try to review this as one of first things after I'm back from PTO.

:sorry:

kkafar avatar Aug 12 '25 15:08 kkafar

Hey, I most likely won't find time tomorrow & I'm going for a two week PTO on Thursday. I'll try to review this as one of first things after I'm back from PTO.

:sorry:

Hey! No worries! Have a nice PTO 😊

johankasperi avatar Aug 12 '25 20:08 johankasperi

@kmichalikk I added support for systemImage (using SF Symbols) in this commit https://github.com/software-mansion/react-native-screens/pull/2987/commits/8981d6a77a8a83d3f09ce1e25d4316f79d333cc9 Feel free to take a look or try it out whenever you have the chance. Thanks!

johankasperi avatar Aug 18 '25 21:08 johankasperi

@kmichalikk refactored everything a bit in https://github.com/software-mansion/react-native-screens/pull/2987/commits/af27795c0535b85ac75c8cf679ed2181b5af6f31

I realised that users might want to combine native UIBarButtonItems and React Nodes in the header left and right. So renamed headerRightBarButtonItems and headerLeftRightBarButtonItems to headerRightItems and headerLeftItems. These two properties now accepts an array containing either dicts for UIBarButtonItems or functions returning a React Node. The new functionality is shown in the screen "ReactNodeButtonDemo".

johankasperi avatar Aug 19 '25 21:08 johankasperi

I wasn't able to properly run this probably because of some issues with linking to react-navigation PR - buttons were not displayed at all. I'll try again later. In the meantime I have two small nitpicks.

My bad! I forgot to push my latest commits to react-navigation. Should be working now

johankasperi avatar Aug 21 '25 11:08 johankasperi

@kmichalikk I added support for hidesSharedBackground: boolean when rendering custom React Elements. Making it possible to show them without the liquid glass effect (see screenshot below). Feel free to have a look and try it out!

Simulator Screenshot - iPhone 16 Pro - 2025-09-02 at 12 05 26

johankasperi avatar Sep 02 '25 10:09 johankasperi

I tested this and it seems to fix several UI issues on iOS 26. Thank you @johankasperi ! 🙏

@kkafar @kmichalikk is there any chance this might be released in the next few days? 😇 We need this to get our app ready for iOS 26 with a deadline in mid September. 🙈

joluet avatar Sep 05 '25 11:09 joluet

I tested this and it seems to fix several UI issues on iOS 26. Thank you @johankasperi ! 🙏

@kkafar @kmichalikk is there any chance this might be released in the next few days? 😇 We need this to get our app ready for iOS 26 with a deadline in mid September. 🙈

Thank you! Don't know your circumstances for the deadline but wanted to share that you can opt out from the new design with UIDesignRequiresCompatibility in your Info.plist

johankasperi avatar Sep 05 '25 11:09 johankasperi

Thank you! Don't know your circumstances for the deadline but wanted to share that you can opt out from the new design with UIDesignRequiresCompatibility in your Info.plist

Apple is considering our App for featuring. So, opting out is no an option for us. :/

joluet avatar Sep 05 '25 11:09 joluet

Thank you! Don't know your circumstances for the deadline but wanted to share that you can opt out from the new design with UIDesignRequiresCompatibility in your Info.plist

Apple is considering our App for featuring. So, opting out is no an option for us. :/

I understand. Congrats for being considered for featuring!

johankasperi avatar Sep 05 '25 11:09 johankasperi

I wanna update you, that I'm starting to look at this PR 😅 I can't say however we'll be able to land in in just couple of days, since it's a bit chunky.

Remember that you always have patch-package at your disposal (know that it is kinda clunky solution, but if forced to - may be a way to go).

kkafar avatar Sep 08 '25 14:09 kkafar

I wonder what is going on with the shadow beneath the bar button items, that disappears after few seconds. @kligarski is that something you experienced when testing iOS 26?

I noticed some unusual shadow behavior with the search bar in the header but I did not pay much attention to it yet as there were more critical bugs with the search bar that could've been impacting the shadows.

kligarski avatar Sep 10 '25 06:09 kligarski

Okay, I'll create ticket for this to test it out on pure native app, to verify whether this is UIKit issue or something on our end.

kkafar avatar Sep 10 '25 07:09 kkafar

I wonder what is going on with the shadow beneath the bar button items, that disappears after few seconds. @kligarski is that something you experienced when testing iOS 26?

I haven't noticed that! I almost hope it's a bug in iOS 26 because I haven't written any code (as far as I know) that should affect that. But good catch!

It is happening on the back button in other demo screens and in the News app from apple. So I'm guessing its part of UIKit

https://github.com/user-attachments/assets/70d592d5-374e-47f0-937e-9fe242c93f28

https://github.com/user-attachments/assets/6996593c-a136-455f-a23c-62069a74a66a

johankasperi avatar Sep 10 '25 20:09 johankasperi

Okay. This looks really good. I have few initial remarks. Please answer them.

Thanks for the review! I think I have adressed all of your remarks. Please let me know if you have any further questions or if there is anything else I should take a look at.

johankasperi avatar Sep 10 '25 20:09 johankasperi

This PR seems promising! Can't wait! Any ETA?

JustJoostNL avatar Sep 13 '25 15:09 JustJoostNL

This needs priority now that iOS26 is released. Just updated Xcode and now all my IconButtons aren't aligned correctly anymore in the headers.

dylancom avatar Sep 16 '25 15:09 dylancom

This needs priority now that iOS26 is released. Just updated Xcode and now all my IconButtons aren't aligned correctly anymore in the headers.

Sorry been stuck with more important bugs in my app. Plan is to adress/fix everything from the latest review tomorrow (Sept 17th). But want to remind you that you can opt-out from the new iOS 26 design in your app with this flag https://github.com/software-mansion/react-native-screens/pull/2987#issuecomment-3257998157

johankasperi avatar Sep 16 '25 20:09 johankasperi

⚠️ No. 4

I'm unable to reproduce this using a single custom view as property to headerRight (copy/pasted your code and running in iPhone 16 Pro). For me the custom view is shown in the header. I also have to put a regular UIBarButton item in the array for the excessive items menu to appear.

Either way, React Elements or custom viesw is not rendered in the excessive items context menu. But if you put to many regular UIBarButtonItems the menu will work as expected:

https://github.com/user-attachments/assets/0c4ae908-a668-421f-aa16-3e83527e5a60

Added an example of this here: https://github.com/software-mansion/react-native-screens/pull/2987/commits/882aea244c412efa0e208ec60adf40a5d7b852f1

johankasperi avatar Sep 17 '25 19:09 johankasperi

⚠️ No. 1 - Notice that the header title appears only after a delay when using spacing. I haven't observed that in other screens.

Good catch! No idea why this is happening. It is not happening on iOS 26 though so I'm guessing it's something in UIKit?

johankasperi avatar Sep 17 '25 20:09 johankasperi

⚠️ No.2 - Header

I am able to reproduce this on the main branch in the "Header Options"-example so don't think this is related to this PR. Should be fixed though but maybe should open a separate issue for this?

https://github.com/user-attachments/assets/c3af7a85-3227-48af-a24f-dd8b371139c5

johankasperi avatar Sep 17 '25 20:09 johankasperi

🚫 No. 3 - POTENTIALLY BLOCKING

I don't think this is a regression. You have to set headerBackVisible: true to make the back button visible if you have defined headerLeft in the current implementation. Tested this on the main branch in the "Header Options" example by setting headerBackVisible: undefined and defining headerLeft.

johankasperi avatar Sep 17 '25 20:09 johankasperi

🚫 / ⚠️ No. 5 (haven't made my mind whether it's blocking or not)

Don't think this is related to this PR either unfortunately. I am able to reproduce this on the main branch as well:

Simulator Screenshot - iPhone 16 Pro - 2025-09-17 at 22 56 02

Also, isn't @t0maboro trying to fix this in https://github.com/software-mansion/react-native-screens/pull/3210?

johankasperi avatar Sep 17 '25 21:09 johankasperi

@kkafar I think I have adressed everything you mentioned in the last review now. Please let me know if I have missed something or if there is something else I need to take a look at. Thank you!

johankasperi avatar Sep 18 '25 15:09 johankasperi

Thank you so much!

Back on it. Will submit review / approval in few hours

kkafar avatar Sep 19 '25 08:09 kkafar