11// Temporary usage until it is integrated
22// https://github.com/necolas/react-native-web/issues/1020
3+ // @ts -ignore: FIX: Fix typing of this module
4+ import FocusTrap from 'focus-trap-react' ;
35import * as React from 'react' ;
46import * as ReactDOM from 'react-dom' ;
5- import { ModalProps } from 'react-native' ;
7+
8+ import { ModalProps } from './Modal' ;
69
710const ESC_KEY = 27 ;
811
9- class Modal extends React . Component < ModalProps > {
12+ class Modal extends React . PureComponent < ModalProps > {
1013 public el : HTMLDivElement ;
1114 public modalRoot : HTMLBodyElement ;
1215 public content : React . RefObject < HTMLDivElement > = React . createRef ( ) ;
@@ -18,10 +21,14 @@ class Modal extends React.Component<ModalProps> {
1821 }
1922
2023 public componentDidMount ( ) {
24+ // TODO: find a better solution
25+ // Currently, when the body height is shorter than the content that is scrollable
26+ // it will jump scroll to top when the modal is opened.
27+ // This hack keeps the body height the same length as the content
28+ document . body . style . position = 'relative' ;
29+ document . body . style . height = 'initial' ;
30+ document . body . style . minHeight = 'initial' ;
2131 this . modalRoot . appendChild ( this . el ) ;
22- if ( this . content . current ) {
23- this . content . current . focus ( ) ;
24- }
2532 }
2633
2734 public componentWillUnmount ( ) {
@@ -38,32 +45,33 @@ class Modal extends React.Component<ModalProps> {
3845 } ;
3946
4047 public render ( ) {
41- const { transparent, visible } = this . props ;
48+ const { transparent, visible, isScrollable = false } = this . props ;
4249
50+ // Prevent body scroll
51+ if ( visible && ! isScrollable ) document . body . style . overflow = 'hidden' ;
52+ // Reset to normal
53+ if ( ! visible ) document . body . style . overflow = '' ;
4354 if ( ! visible ) return null ;
4455
45- return (
46- < div >
47- { ReactDOM . createPortal (
48- < div
49- ref = { this . content }
50- onKeyDown = { this . handleKeyDown }
51- tabIndex = { - 1 }
52- style = { {
53- backgroundColor : transparent ? 'transparent' : 'white' ,
54- bottom : 0 ,
55- left : 0 ,
56- position : 'fixed' ,
57- right : 0 ,
58- top : 0 ,
59- zIndex : 1000 ,
60- } }
61- >
62- { this . props . children }
63- </ div > ,
64- this . el ,
65- ) }
66- </ div >
56+ return ReactDOM . createPortal (
57+ < FocusTrap >
58+ < div
59+ ref = { this . content }
60+ onKeyDown = { this . handleKeyDown }
61+ style = { {
62+ backgroundColor : transparent ? 'transparent' : 'white' ,
63+ bottom : 0 ,
64+ left : 0 ,
65+ position : isScrollable ? 'absolute' : 'fixed' ,
66+ right : 0 ,
67+ top : 0 ,
68+ zIndex : 1000 ,
69+ } }
70+ >
71+ { this . props . children }
72+ </ div >
73+ </ FocusTrap > ,
74+ this . el ,
6775 ) ;
6876 }
6977}
0 commit comments