Code Monkey home page Code Monkey logo

Comments (14)

ericvicenti avatar ericvicenti commented on May 18, 2024 6

So I'm picturing something roughly like this:

const App = ModalNavigator({
  Main: StackNavigator({
    ...
  }),
  RateAppDialog,
  SupportModal
});

The idea is, RateAppDialog is a component which takes special props and manages its own transition, gesture, and view masking. Including adding the back action when the mask is tapped.

SupportModal would also manage its own animation and gesture, but because it is covers the full screen, it would somehow report to the ModalNavigator when the transition completes, so that ModalNavigator knows when it can unmount previous screens.

Keep in mind, we couldn't easily use this API for StackNavigator card-mode! Whys that? Because the translate of the previous screen needs to somehow be aware of the gesture happening on the next screen, (damn iOS transitions!). Not to mention header composition. So yeah, lets please leave StackNavigator card-mode and header out of this proposal! πŸ™

If you're liking this stuff @brentvatne, I can get started on a real RFC here. Between this modal cleanup project and @grabbou's card stack hacks, I think we'll be on a solid track for flexible animations!

from rfcs.

dantman avatar dantman commented on May 18, 2024 4

The exact UI of a modal, whatever kind it is, doesn't have to be defined by React Navigation. I think we can break down pretty much any type of modal into a common set of route features the modal needs in order to work as a React Navigation route that will allow the screen component to take over and do whatever it wants.

The ones I can think of so far:

  • Does the route show the previous screen in the stack below it? This would make the implied background transparent instead of opaque and disable any optimization for the previous screen that would make React Native hide/clip the views in it instead of rendering them.
    • Does tapping on the transparent background of the route imply BACK navigation?
    • What is the color of the translucent background? Or what is the component responsible for rendering it. (maybe per-route cardStyle control would be enough for this)
  • Does the route leave the header alone, letting the header from the previous route show through instead of transitioning to a new header with a title and actions for the current route?
  • Does the route have a transition for entry/exit other than the one used by the StackRouter? (We might even want to make it so the StackNavigator modal config can be per-route.
  • headerMode may also need to be per-route so we can do full-screen dialogs.

A menu:

  • Shows the route below it.
  • Doesn't have a translucent background color, but does imply a BACK.
  • Leaves the header alone.
  • Doesn't have a screen transition.

A dialog:

  • Shows the route below it.
  • May have a translucent background color, but may not imply a BACK depending on the circumstances.
  • Leaves the header alone.
  • May have a custom screen transition, or none if someone wants to use some library's built-in animations.

A full-screen dialog:

  • Does not show the route below it.
  • Has a separate header?
  • Has a separate transition, like the mode: 'modal' transition.

We could even have responsive dialogs that switch settings based on the screen dimensions. i.e. on mobile the navigationOptions would return the settings used for a dialog and on a tablet would return the settings for a full-screen dialog.

from rfcs.

brentvatne avatar brentvatne commented on May 18, 2024 3

no plans to use the native modal component

from rfcs.

satya164 avatar satya164 commented on May 18, 2024 3

how about an API similar to React DOM Portals?

// somewhere inside your render method
<View>
  {this.props.navigation.createModal(
    // whatever it's rendered here will be rendered on top of current screen
    <Text>this is modal content</Text>
  )}
</View>

we could also export a <Modal /> component which
gets the navigation prop via context and uses this API internally.

in react-native-paper we stopped using our Portal component by default, so if react-navigation had this API, users will be able to use it easily.

from rfcs.

ericvicenti avatar ericvicenti commented on May 18, 2024

There are so many types of modals, when you think about it! I think most NUX, popovers, and dropdowns should also be considered modals, because they respond to the Android back button and escape key, they cover up other content on the screen, and are dismiss-able by tapping away.

from rfcs.

ericvicenti avatar ericvicenti commented on May 18, 2024

I'm loving the exploration! One idea for simplification: ignore the header in this proposal entirely, and focus on full-screen behavior. We can always nest a StackNavigator "card mode" navigator inside the modal, which is the current, explicit way of specifying this. I expect that many users of the library already have a modal-mode stack on the outside, and this "ModalNavigator" could be a replacement for that.

In the distant future, I think we could use some shared element magic within "ModalNavigator" to re-implement StackNavigator-card and all of the fancy transitions. This would effectively flatten the navigation state to a single stack, which is what a lot of people are kind of clamoring for, but I think it will be a while before we can do this. The complication with header configuration is the main reason stack flattening isn't possible on todays code.

If it seems too boilerplatey to have people wrap their existing card-mode StackNavigator in ModalNavigator, we could figure out how to automagically wrap the ModalNavigator if there isn't one at the top level, such that modal features are always available.

We could even have responsive dialogs that switch settings based on the screen dimensions. i.e. on mobile the navigationOptions would return the settings used for a dialog and on a tablet would return the settings for a full-screen dialog.

This is an awesome idea, and I think we should make sure its entirely possible to do things like this in user-space. We won't have all the answers here, but we can implement some awesome defaults, like the tablet dialog vs full-screen-modal use case you mentioned.

from rfcs.

 avatar commented on May 18, 2024

can react navigation can support different animations for stack children?

from rfcs.

brentvatne avatar brentvatne commented on May 18, 2024

@tomatoo - wrong issue: #10 (comment)

from rfcs.

benadamstyles avatar benadamstyles commented on May 18, 2024

Sorry to butt in here but I just wanted to ask – are you planning to use the native modal in this new modal navigator? If so, I'd like to mention now that the whole reason I had to refactor my app to use a react-navigation modal stack was to avoid issues that I have been having with the native modal on the native side, so hopefully you can keep the new modal navigator as a JS-only solution πŸ™‚ if that was already the case please ignore this and sorry for the unnecessary notification.

from rfcs.

brentvatne avatar brentvatne commented on May 18, 2024

@satya164 - I'd be interested in seeing a RFC for that approach!

from rfcs.

satya164 avatar satya164 commented on May 18, 2024

will do

from rfcs.

lxcid avatar lxcid commented on May 18, 2024

I want to add that @dantman break down at #15 (comment) is much better for me:

I'm more familiar with iOS and a bit of Web so I'm gonna try to make the case for @dantman argument base on what I am familiar with… If anyone is familiar with android, feel free to make correction. :)

Based on WAI-ARIA Authoring Practices 1.1: Dialog Modal, Dialog Modal is described as:

A dialog is a window overlaid on either the primary window or another dialog window. Windows under a modal dialog are inert. That is, users cannot interact with content outside an active dialog window. Inert content outside an active dialog is typically visually obscured or dimmed so it is difficult to discern, and in some implementations, attempts to interact with the inert content cause the dialog to close.

There's a few interesting terms to define here:

  • Window: Root view of a route
  • Primary Window: The window to receive input events from user.
  • Dialog: A type of view that overlay over primary window or other dialog
  • Modal: To receive input events if its at the top of the stack.

In iOS windowing system, there's UIWindow which also have the concept of primary window called key window. You can become or resign from being primary window and they stack up, although in iOS u can jump the queue by becoming key window again. This is how UIAlertController are presented

So, based on @ericvicenti examples at #15 (comment), I would make the follow changes:

// I think window is more appropriate naming, we are basically tracking primary window
const createWindowNavigator = createStackNavigator;
const App = createWindowNavigator(
  {
    MainWindow: createStackNavigator({
      ...mainScreens,
    }),
    RateAppModalDialog: {
      screen: RateAppModalDialog,
      fullscreen: false, // hint to the navigator to keep previous primary window in stack
    },
    SupportModalDialog, // default to fullscreen: true
  },
  {
    headerMode: 'none',
    initialRouteName: 'MainWindow', // The initial primary window is Main
    mode: 'modal',
  },
);

So I would say non-modal dialog is out of react navigation scope.

A modal dialog will be a window dialog and a non modal dialog will be a non window (a.k.a view) dialog. Tooltip can be considered a non modal dialog and doesn't seems like a responsibility for React Navigation. For me, I would categorize @satya164 solution #15 (comment) as non-modal dialog as it share input events with the current window, although if it implement React portal like behaviour, it potentially could mimic a modal dialog, but to keep things simple, I think we assume its non-modal dialog.

(Also, we could potentially use React portal for createWindowNavigator() if it make sense)

What could be a modal dialog?

  • Full Screen Modal Dialog: In iOS, you see that often, they get presented from the bottom up. They obscure the window behind you so the navigator can optimise by removing the screen. (Although React have no concept of hidden component, just mount vs unmount)
  • Non Full Screen Modal Dialog: Usually the background is dimmed but not necessary, the dialog might be floating or anchored to a side of screen (bottom/top) only partially obscuring the previous primary window. E.g. are contextual menu, Alert View, Action Sheet, etc.

In iOS, iPad/iPhone usually present modal as non full screen modal dialog in portrait orientation and full screen modal dialog in landscape orientation. So we just need to be able to dynamically control the configuration at orientation change?

from rfcs.

brentvatne avatar brentvatne commented on May 18, 2024

from: react-navigation/react-navigation#5808


react-native 3.5.1
@react-navigation/core 3.2.0
@react-navigation/web 1.0.0-alpha.7

My use case is: I'm coming from react-native and now I have to implement a react-native-web implementation based on it. My "mobile app" is implemented on part of the screen. The screen also contains other components. The modal implementation from react-navigation is far too limited to be able to use comfortably on a wider screen scenario. Here are some of the things I ran into.

Initially, I implemented https://github.com/Dekoruma/react-native-web-modal/tree/master/packages/modal-enhanced-react-native-web
It offers an experience that allows you to implement a modal that displays e.g. on a large screen as a centered box with a transparent background. It dropped the ball in one area though, it also applies the centered box with transparent background approach on a mobile screen, where you want pure full screen. But basically, it works.

So, I started looking at react-navigation. Also because I assumed that it would be better integrated with things like back button press, swipes, etc and I like to keep navigation logic centralized. Also, I like to use the default header with a back button on full screen mobile, but something more like a default modal header without back button on a desktop screen.

First pass

  • I applied a modal stack and ran the app
  • When I opened a modal, it behaved just like a normal screen, but no animation was applied (I expected bottom slide in)

Second pass

  • I applied a contentComponent key on the modal stack, and applied a transparent wrapper that centered the children. No joy. Turns out, unlike the drawerNavigator, the stackNavigator doesn't use a contentComponent (why not? Would be great for analytics processing, customization etc)

Third pass

  • i applied a wrapper on a per screen basis and set headerMode to screen. Kinda sucky bc it means duplication
  • The header is full screen instead of modal width
  • The wrapper does work, however, the Modal is contained to the area of the screen that contains the "mobile app" it doesn't do a full screen center. Only in the navigation area covered by react-navigation, I guess I have to make the wrapper fixed positioned but I already know this is a dead end
  • There is no animation

So, at this point, I have to admit defeat. react-navigation modals are not yet ready for cross platform use. As a short term fix, I would recommend implementing contentComponent. This will allow use to create a fixed position wrapper and a centered flexbox which right away offers the basics.

Requirements for me:

  • cross platform defaults (screen centered on web, full screen on mobile), with customization options (transparency colors, positioning (center, bottom, left, right, top), height width etc
  • ideally screen width specific customization
  • swipe close handling on mobile, click transparent area plus X for close on web, tablet mixed

from rfcs.

vamshi9666 avatar vamshi9666 commented on May 18, 2024

How about a prop isModal to screen.

Code will look like

 <UserStack.Navigator>
     <UserStack.Screen name="list" /> //normal screen
     <UserStack.Screen name="addUser" isModal={true}  />. //modal screen
 </UserStack.Navigator>

from rfcs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.