Closed shirakaba closed 4 years ago
Hi,
We've been thinking about implementing something like this. In practice, when we show modals, we make "fullscreen" mask, usually even with the transparent background, so its coordinates are always fullscreen and it never goes outside of its boundaries.
But if this to be a more controlled feature, I would suggest to implement it in the way where you can set a prop named something like focusBoundary
, which restricts the navigation within the focusable component when it is doing smartNavigate
in the SpatialNavigation.js
. There is a place where it tries to find siblings, then if it doesn't find them, it delegates the directional function to its parent. So this is the moment where you can check for this prop, and if it has focusBoundary=true
, do not propagate up to the parent.
I unfortunately missed the notification of this comment so I went ahead and implemented enabled
, which solves my immediate use-case.
I believe that there is probably scope for both an enabled
prop (which is particularly well suited for disabling a submission button while a request is in progress) and a focusBoundary
prop (perhaps admittedly more suited to my issue of restricting focus to within the bounds of a modal).
I was able to apply enabled
for my use-case by toggling enabled={false}
for every component on my screen whenever a modal is presented. Setting a focusBoundary
prop on a single focusable sounds far more attractive, but then again, you say it's based on direction, and my components are actually on-screen (just hidden, e.g. with opacity: 0
), so there may be some difficulties there.
I believe this PR also addresses this use-case: https://github.com/NoriginMedia/react-spatial-navigation/pull/72 So perhaps we can close this :)
Is your feature request related to a problem? Please describe. I'm using
react-navigation
together with React Native and React Native Web. It's working nicely, but poses some challenges for usage withreact-spatial-navigation
.In my app, I have a MainMenu screen with a selection of items to pick from. Upon picking an item, a modal will open, showing the VideoModal screen, which presents both a video and a set of related items (that are focusable).
I achieve this flow using a StackNavigator, which renders one screen at a time and provides transitions between screens. When a new screen is opened it is placed on top of the stack.
The problem is that StackNavigator does not unmount the previous screen when presenting the modal; it merely hides it. Thus, the focusables are all still mounted, and so if the user presses up/down/left/right, the focus may leave the bounds of the screen and select these hidden focusables. Instead, it should ignore those hidden modals belonging to a different route.
Describe the solution you'd like I'd like an
enabled
prop (defaults totrue
) to include/exclude any focusable from the tree of 'available' focusables. I could toggled this totrue
/false
based on whether the given navigation route is active (visible) or not.Describe alternatives you've considered In practice, I write my route names into the
focusKey
(e.g.MainMenu/Carousel
andVideoModal/Carousel
) as if to compose a directory hierarchy. Routes could be excluded based on string-matching with thefocusKey
, but this requires users of the library to be diligent with how they name their focus keys and may harm component re-use.