Skip to content
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

feat(iOS): add support for medium detent #1649

Merged
merged 38 commits into from
Dec 14, 2022
Merged

Conversation

kkafar
Copy link
Member

@kkafar kkafar commented Dec 1, 2022

Description

Add support for sheetPresentationController by exposing new props. These changes work on both architectures (Fabric & Paper).

Known issues:

  • Transition animations between detent sizes are not working on Fabric.

Nevertheless after the review process I'm gonna merge this PR as it is getting to big and address these issues in separate PRs.

Changes

  • Added sheetAllowedDetens prop

    • Describes heights where a sheet can rest.
    • Works only when stackPresentation is set to formSheet.
    • Defaults to large.
  • Added sheetCornerRadius prop

    • The corner radius that the sheet will try to render with.
    • Works only when stackPresentation is set to formSheet.
    • If left unset system default is used.
  • Added sheetLargestUndimmedDetent prop

    • The largest sheet detent for which a view underneath won't be dimmed.
    • Works only when stackPresentation is set to formSheet.
    • If this prop is set to:
      • large - the view underneath won't be dimmed at any detent level
      • medium - the view underneath will be dimmed only when detent level is large
      • all - the view underneath will be dimmed for any detent level
    • Defaults to all.
  • Added sheetGrabberVisible prop

    • Boolean indicating whether the sheet shows a grabber at the top.
    • Works only when stackPresentation is set to formSheet.
    • Defaults to false.
  • Added sheetExpandsWhenScrolledToEdge prop

    • Whether the sheet should expand to larger detent when scrolling.
    • Works only when stackPresentation is set to formSheet.
    • Defaults to true.
  • Added noop implementations for Android

  • Updated view manager interfaces for Paper

Screenshots / GIFs

Test code and steps to reproduce

Test1649 in TestsExample & FabricTestExample

Checklist

@kkafar kkafar self-assigned this Dec 1, 2022
@kkafar kkafar changed the title feat: add support for iOS medium detent feat(iOS): add support for medium detent Dec 8, 2022
@kkafar kkafar marked this pull request as ready for review December 8, 2022 19:00
Copy link
Member Author

@kkafar kkafar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes for reviewers below.

I would gladly hear some comments on prop naming.

Comment on lines +22 to +27
+ (RNSScreenDetentType)RNSScreenDetentTypeFromAllowedDetents:
(facebook::react::RNSScreenSheetAllowedDetents)allowedDetents;

+ (RNSScreenDetentType)RNSScreenDetentTypeFromLargestUndimmedDetent:
(facebook::react::RNSScreenSheetLargestUndimmedDetent)detent;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codegen generates two different types of enums despite the fact, that only single type is used in JS component spec, thus 2 distinct conversion methods are required.

Comment on lines +673 to +674
// This must be called after setter for stackPresentation
[self updatePresentationStyle];
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This it the case, because retrieving sheetPresentationController from view controller requires modalPresentationStyle to be set to one of UIModalPresentationPageSheet or UIModalPresentationFormSheet. We do not support UIModalPresentationPageSheet, nevertheless this is done inside stackPresentation setter.

On Paper this effect is achieved by calling this method in didSetProps: method.

Comment on lines 156 to 159
sheetAllowedDetents = 'large',
sheetLargestUndimmedDetent = 'all',
isSheetGrabberVisible = false,
sheetCornerRadius = -1.0,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder whether these default values will work with react-navigation, because I remember some shenanigans with default value for gestureResponseDistance prop.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-navigation will have to add this code by itself since they have their own NativeStackView.

Copy link
Member

@WoLewicki WoLewicki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! I left some comments, please answer them before merging.

guides/GUIDE_FOR_LIBRARY_AUTHORS.md Show resolved Hide resolved
src/native-stack/types.tsx Outdated Show resolved Hide resolved
Comment on lines 156 to 159
sheetAllowedDetents = 'large',
sheetLargestUndimmedDetent = 'all',
isSheetGrabberVisible = false,
sheetCornerRadius = -1.0,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

react-navigation will have to add this code by itself since they have their own NativeStackView.

src/types.tsx Show resolved Hide resolved
ios/RNSScreen.h Outdated Show resolved Hide resolved
Copy link
Member

@kacperkapusciak kacperkapusciak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Amazing job on this PR so far 🎉
Some general remarks:

Android has a similar concept to iOS detents with bottom sheets. If we ever add a support for this in screens (and I think we should) we definitely should have a unified API for both iOS detents and Android bottom sheets at the same time.

For API I kinda like the @gorhom 's API with snapPoints naming and due to the popularity of react-native-bottom-sheet it's something react-native developers are familiar with: https://gorhom.github.io/react-native-bottom-sheet/props#snappoints

To your implementation:
besides passing a few predefined detents iOS 16 also allows to pass a custom detent, I would love to see this implemented as well - customizing and resizing sheets in UIKit. Of course it can be in a separate PR but it's something we should keep in mind.

Cheers ✌️

@kkafar
Copy link
Member Author

kkafar commented Dec 14, 2022

For API I kinda like the @gorhom 's API with snapPoints naming and due to the popularity of react-native-bottom-sheet it's something react-native developers are familiar with: https://gorhom.github.io/react-native-bottom-sheet/props#snappoints

I'll address naming issues when API for Android will be ready (yes, it is planned), because I do not know yet what terminology / conventions Android uses exactly. Thank you for suggestions though, I will most likely go into that direction.

besides passing a few predefined detents iOS 16 also allows to pass a custom detent, I would love to see this implemented as well - customizing and resizing sheets in UIKit. Of course it can be in a separate PR but it's something we should keep in mind.

I'm aware of possibility of specifying custom detent sizes, although it comes with few extra steps. I'll do it separate PR for sure, as this one gets too big.

I'm going to merge this PR and iterate over the new API in followups.

@kkafar kkafar merged commit 914730d into main Dec 14, 2022
@kkafar kkafar deleted the @kkafar/ios-medium-detent branch December 14, 2022 10:25
@gorbypark
Copy link
Contributor

It appears that when using 3.19.0 with react-navigation, presentation: 'formSheet' is defaulting to "half screen" height, when reading above it seems like it was intended to be "large" (which I assume is the old nearly full screen (~90%) height)? It doesn't seem like the props to configure the formSheet behaviour has been added to react-navigation yet, afaict. I've attached a screenshot of what detent I'm getting by default.

Screen Shot 2023-01-19 at 9 39 10 AM

@kkafar
Copy link
Member Author

kkafar commented Jan 19, 2023

Hi @gorbypark,

This PR was not included in version 3.19.0 of react-native-screens, because we are still having some internal conversations on prop naming and shape of the final API (especially, that we need to have it unified with Android implementation which is not ready yet).

It will most likely be released with next minor version.

@gorbypark
Copy link
Contributor

Hi @gorbypark,

This PR was not included in version 3.19.0 of react-native-screens, because we are still having some internal conversations on prop naming and shape of the final API (especially, that we need to have it unified with Android implementation which is not ready yet).

It will most likely be released with next minor version.

Aha! Sorry for jumping the gun, I've been tracking this PR for a while since I'm interested in the feature! When I saw the weird half-height formSheet and a new release just a few days ago, I just assumed it had been merged! I guess I have to do some more investigation as to what's going on with my formSheet.

Thanks!

@ferrannp
Copy link
Contributor

ferrannp commented Jan 25, 2023

@kkafar this is awesome that we will finally have native sheets. Excited to see them on Android too. Is there any branch I can watch? Let me know if you need any help with implementation or testing 🙏 .

By the way I noticed something on iOS that seems like a bug, when you collapse the sheet fast, there is a jumping in the bottom (seeing the content behind from the bottom):

bottomJump.mov

kkafar added a commit that referenced this pull request Jan 27, 2023
## Description

Earlier when calling `updatePresentationStyle` in `RNSScreen` we have
relied on order of method calls and kept our fingers crossed that the
order would not be violated with future changes.

Now we leverage `finalizeUpdates:` method from
`RCTComponentViewProtocol` which is called after all updates are applied
to the component.

For broader context see #1649 (comments).

## Changes

Moved call to `updatePresentationStyle` from `updateProps` to
`finalizeUpdates`.


## Test code and steps to reproduce

See `Test1649` (everything should work as before)

## Checklist

- [x] Ensured that CI passes (iOS e2e is a known issue)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants