-
-
Notifications
You must be signed in to change notification settings - Fork 609
feat(iOS): add pageSheet presentation for native-stack #2793
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have found that this API got exposed by Apple:
& it is equivalent of the one in SwiftUI https://developer.apple.com/documentation/swiftui/presentationsizing
From the docs:
Discussion
The default value is true. The default value indicates the sheet uses UIModalPresentationPageSheet behavior, in which the sheet width follows the readable width.When the value is set to false, the sheet uses UIModalPresentationFormSheet behavior, in which the sheet size follows the presented view controller’s preferredContentSize.
So I guess we have a couple of ways of solving this now.
1. Expose global switch in JS
We could expose global switch in JS to let users decide on the desired behaviour.
E.g. in utils.ts, where we have compatibilityFlags right now, we could add add a new global object & let users mutate it.
We would then read the value & pass it down via extra prop on screen & select appropriate behaviour.
2. Expose the switch on Screen definition level
Basically the same idea as above, but the prop can be passed to each Screen directly, allowing for a bit more of flexibility.
3. Treat is as the fix & restore the old behaviour
We could use the new API to restore the old behaviour w/o exposing any customisation option to the user.
4. Mix of previous 3
☝🏻
Summary
The change introduced in iOS between 17 & 18 is treated as breaking by the users, and indeed can be seen as one.
Therefore first thing to do, would be to restore the previous behaviour. We want to go back to using UIModalPresentationPageSheet on iOS 18 and above.
To achieve this we could e.g. use the new API & update the modal behaviour documentation, to indicate that it does enforce pageSheet on iOS >= 18. Later, when releasing Screens 5.0 we could restore the modal to just use UIModalPresentationAutomatic, but for now we want to mitigate this breaking change.
Second thing to do is to expose new system behaviour somehow. We expose formSheet presentation type & it uses UIModalPresentationFormSheet underneath, therefore can be used to achieve this, however due to #2045 and series of later changes it is treated a bit specially now (has layout limitations etc.), and due to that comes with series of pain points.
Therefore the action points:
- Restore pagesheet behaviour in regular size classes (e.g. by using the new API)
- update the modal documentation, to indicate that it not only uses
UIModalPresentationAutomaticbut also theprefersPageSizing(effectively usingUIModalPresentationPageSheet) - We'll expose the
pageSheetoption later, after we fix above ☝🏻 (this will also be released on v4 line) - We'll restore the
modalpresentation behaviour to useUIModalPresentationAutomaticpurely in[email protected](next major)
|
Okay. The change for v4 is here: #2797. |
## Description Brings back `stackPresentation: 'modal'`'s size on iOS 18.0+. Since the release of iOS 18, screens with `stackPresentation: 'modal'` changed size on devices with a bigger screen, such as an iPad - they became much smaller, which impacted applications of the library's users (see issue #2549). This happens because `UIModalPresentationAutomatic`, which is used by `react-native-screens` for modal on iOS, has been changed with the release of iOS 18. `UIModalPresentationAutomatic` is now mapped to `UIModalPresentationFormSheet` for iOS >=18 and `UIModalPresentationPageSheet` for earlier versions (this was the default before). For more context please see PR #2793 but the TL;DR is that we consider this a breaking change for our users and therefore we decided to bring back the old behavior for `react-native-screens` v4 using [`prefersPageSizing`](https://developer.apple.com/documentation/uikit/uisheetpresentationcontroller/preferspagesizing?language=objc) property of the `UISheetPresentationController` which has been available since iOS 17.0+. Resolves #2549. ## Changes - use `prefersPageSizing` for modal on iOS 18.0+ ## Screenshots / GIFs ### Before  ### After  ## Test code and steps to reproduce Open `Modals` example screen and use `Open modal` button. ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes --------- Co-authored-by: Kacper Kafara <[email protected]>
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks solid, good job 💪🏻
I have a question 👇🏻 and I haven't tested the runtime yet.
|
Also do we have a PR prepared for |
|
PR for |
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Answered
kkafar
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're good. Let's proceed.
**Motivation** Since the release of iOS 18, screens with`presentation: 'modal'` changed size on devices with a bigger screen, such as an iPad - they became much smaller, which impacted applications of the library's users (see issue software-mansion/react-native-screens#2549). To address the issue, `react-native-screens` will introduce new presentation type for native stack (`pageSheet`) that will allow users to use previous modal behavior (see PR software-mansion/react-native-screens#2793). The behavior of `pageSheet` on Android will be the same as `modal`. Please note that in `react-native-screens`, behavior of regular `modal` has been aligned with previous behavior internally via [`prefersPageSizing` UIKit prop](software-mansion/react-native-screens#2797) in order not to introduce breaking changes. In the future major release of `react-native-screens` however this will be aligned to fully native behavior. This PR contains changes required to support `pageSheet` in `react-navigation`. **Test plan** Open Stack Presentation and Modals example screens in example apps from `react-native-screens` and open a `pageSheet`.
**Motivation** Since the release of iOS 18, screens with`presentation: 'modal'` changed size on devices with a bigger screen, such as an iPad - they became much smaller, which impacted applications of the library's users (see issue software-mansion/react-native-screens#2549). To address the issue, `react-native-screens` will introduce new presentation type for native stack (`pageSheet`) that will allow users to use previous modal behavior (see PR software-mansion/react-native-screens#2793). The behavior of `pageSheet` on Android will be the same as `modal`. Please note that in `react-native-screens`, behavior of regular `modal` has been aligned with previous behavior internally via [`prefersPageSizing` UIKit prop](software-mansion/react-native-screens#2797) in order not to introduce breaking changes. In the future major release of `react-native-screens` however this will be aligned to fully native behavior. This PR contains changes required to support `pageSheet` in `react-navigation`. **Test plan** Open Stack Presentation and Modals example screens in example apps from `react-native-screens` and open a `pageSheet`.
Description
Adds new presentation for Native Stack -
pageSheet(UIModalPresentationPageSheetmodal style on iOS,modalon Android).Since the release of iOS 18, screens with
stackPresentation: 'modal'changed size on devices with a bigger screen, such as an iPad - they became much smaller, which impacted applications of the library's users (see issue #2549). This happens becauseUIModalPresentationAutomatic, which is used byreact-native-screensformodalon iOS, has been changed with the release of iOS 18.UIModalPresentationAutomaticis now mapped toUIModalPresentationFormSheetfor iOS >=18 andUIModalPresentationPageSheetfor earlier versions (this was the default before).Apple added SwiftUI API (link) to allow to choose the behavior of the modal (It turns out there is a new property inform,page,fittedor a custom one) but I wasn't able to find an equivalent functionality in UIKit.UISheetPresentationController, see hereWe considered 3 possible solutions to this problem:
UIModalPresentationAutomatictoUIModalPresentationPageSheetforstackPresentation: 'modal'to bring back old behavior for all modals:stackPresentation: 'modal'should useUIModalPresentationAutomaticorUIModalPresentationPageSheetstackPresentationthat would useUIModalPresentationPageSheeton iOS and a regularmodalon Android:AutomaticorPageSheetbehavior per-screen basis,We decided on the third option.
tvOS does not allow
UIModalPresentationPageSheetso it fallbacks toUIModalPresentationFullScreen(the same behavior asUIModalPresentationAutomatic).This change will require changes to
react-navigation/native-stackas well.Resolves #2549.
Changes
pageSheetexamples inStack PresentationandModalsexample screensScreenshots / GIFs
modalpageSheetTest code and steps to reproduce
Open
Stack Presentation,Modalsexample screens and openpageSheet(at the moment, you might need to manually addpageSheetin react-navigation filespackages/native-stack/src,packages/native-stack/src/utils/getModalRoutesKeys.ts,packages/native-stack/src/views).Checklist