@@ -27,6 +27,20 @@ class Dialog extends Component {
2727 // select body element to add Dialog component too
2828 // eslint-disable-next-line compat/compat
2929 bodyElm = document . querySelector ( 'body' ) ;
30+ scrollX = 0
31+ scrollY = 0
32+
33+ // restore scroll position
34+ restoreOriginalScrollPosition = ( ) => {
35+ if ( this . props . focusElementOnClose ?. focus ) {
36+ this . props . focusElementOnClose . focus ( ) ;
37+ } else {
38+ document . querySelector ( 'html' ) ?. scroll ( {
39+ top : this . scrollY ,
40+ left : this . scrollX
41+ } ) ;
42+ }
43+ }
3044
3145 handleCloseClick = ( e ) => {
3246 this . props . onClose ( e ) ;
@@ -36,19 +50,32 @@ class Dialog extends Component {
3650 handleKeyPress = event => {
3751 if ( event . key === 'Escape' || event . key === 'Esc' ) {
3852 this . handleCloseClick ( event ) ;
53+ this . restoreOriginalScrollPosition ( ) ;
3954 }
4055 } ;
4156
42- // add event listener for escape key
57+ // add event listener for escape key, save scroll position
4358 componentDidMount ( ) {
4459 document . addEventListener ( 'keydown' , this . handleKeyPress , false ) ;
60+ if ( this . props . show ) {
61+ this . scrollX = window . scrollX ;
62+ this . scrollY = window . scrollY ;
63+ }
4564 }
4665
4766 // remove event listener for escape key
4867 componentWillUnmount ( ) {
4968 document . removeEventListener ( 'keydown' , this . handleKeyPress , false ) ;
5069 }
5170
71+ componentDidUpdate ( prevProps ) {
72+ if ( ! prevProps . show && this . props . show ) {
73+ this . scrollX = window . scrollX ;
74+ this . scrollY = window . scrollY ;
75+ }
76+ }
77+
78+
5279 render ( ) {
5380 const {
5481 actions,
@@ -149,7 +176,7 @@ class Dialog extends Component {
149176 < div className = { classnames ( `${ cssNamespace } -bar__right` ) } >
150177 { React . Children . toArray ( actions ) . map ( ( child , index ) => (
151178 < div className = { classnames ( `${ cssNamespace } -bar__element` ) } key = { index } >
152- { React . cloneElement ( child , { className : classnames ( `${ cssNamespace } -dialog__decisive-button` ) , onClick : disableAutoClose ? child . props ?. onClick : chain ( this . handleCloseClick , child . props ?. onClick ) } ) }
179+ { React . cloneElement ( child , { className : classnames ( `${ cssNamespace } -dialog__decisive-button` ) , onClick : disableAutoClose ? chain ( this . restoreOriginalScrollPosition , child . props ?. onClick ) : chain ( this . handleCloseClick , this . restoreOriginalScrollPosition , child . props ?. onClick ) } ) }
153180 </ div >
154181 ) ) }
155182 </ div >
@@ -184,6 +211,8 @@ Dialog.propTypes = {
184211 /** Additional props to disable auto closing dialog */
185212 disableAutoClose : PropTypes . bool ,
186213 /** Additional props to be spread to the footer of the dialog */
214+ focusElementOnClose : PropTypes . object ,
215+ /** Additional props containing an HTMLElement to be focused when the dialog closes. The element must be focusable. */
187216 footerProps : PropTypes . object ,
188217 /** Text or Custom React node for the components header */
189218 header : PropTypes . oneOfType ( [
0 commit comments