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

Functionality for rendering a single modal over a stack #9

Open
codybrouwers opened this issue Sep 11, 2022 · 2 comments
Open

Functionality for rendering a single modal over a stack #9

codybrouwers opened this issue Sep 11, 2022 · 2 comments

Comments

@codybrouwers
Copy link
Contributor

Hi there, thank you for the great library, it is a great abstraction over the bottom sheet library for routing!

An issue I came across was needing to show a single bottom sheet in a transparent modal over a screen like this:

const Stack = createNativeStackNavigator();
const BottomSheet = createBottomSheetNavigator();

function MyModal() {
  return (
    <BottomSheet.Navigator>
      <BottomSheet.Screen
        component={MyModalComponent}
        name="MyModal"
        options={MyModalComponent.options}
      />
    </BottomSheet.Navigator>
  );
}

export function HomeStack() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        component={HomeScreen}
        name="Home"
      />
      <Stack.Group screenOptions={{ presentation: "transparentModal" }}>
        <Stack.Screen
          component={MyModal}
          name="MyModalBottomSheet"
        />
      </Stack.Group>
    </Stack.Navigator>
  );
}

If my HomeStack has lots of other screens that I don't want to be shown as bottom sheets then the above I think is the only option. But this library seems to require that the first screen in the bottom sheet navigator be your app content, not a modal. I'm not sure the best solution but I've added the below patch with a firstScreenIsModal option to always show the bottom sheet provider if true.

I'm happy to submit a PR with the below patch if you think it is a good approach but wanted to get your thoughts on it first!

Patch
// in BottomSheetView.tsx
+  const firstScreen = descriptors[state.routes[0].key];
+  const { firstScreenIsModal = false } = firstScreen.options
+
   // Avoid rendering provider if we only have one screen.
-  const shouldRenderProvider = React.useRef(false);
+  const shouldRenderProvider = React.useRef(firstScreenIsModal);
   shouldRenderProvider.current =
     shouldRenderProvider.current || state.routes.length > 1;
 
-  const firstScreen = descriptors[state.routes[0].key];
   return (
     <>
-      {firstScreen.render()}
+      {firstScreenIsModal ? null : firstScreen.render()}
       {shouldRenderProvider.current && (
         <BottomSheetModalProvider>
-          {state.routes.slice(1).map((route) => {
+          {state.routes.slice(firstScreenIsModal ? 0 : 1).map((route) => {
             const { options, navigation, render } = descriptors[route.key];
@janicduplessis
Copy link
Member

janicduplessis commented Sep 12, 2022

I was thinking maybe passing the app content as a navigator prop instead of using the first screen would be better. This should solve this case.

@codybrouwers
Copy link
Contributor Author

Yep that would work as well!

I'm not sure I'll have time to put together a PR for a little while as my solution above has solved my immediate need but will come back to it later and let you know before I try implementing your idea!

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

No branches or pull requests

2 participants