Fixed: Modal scrolling causing app to scroll on iOS

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
This commit is contained in:
Qstick 2019-08-04 22:39:39 -04:00
parent 2273be5afd
commit a09611a580
9 changed files with 78 additions and 12 deletions

View File

@ -4,7 +4,7 @@ import React, { Component } from 'react';
import { Manager, Popper, Reference } from 'react-popper';
import classNames from 'classnames';
import getUniqueElememtId from 'Utilities/getUniqueElementId';
import isMobileUtil from 'Utilities/isMobile';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import * as keyCodes from 'Utilities/Constants/keyCodes';
import { icons, sizes, scrollDirections } from 'Helpers/Props';
import Icon from 'Components/Icon';

View File

@ -29,6 +29,12 @@
overflow: hidden !important;
}
.modalOpenIOS {
position: fixed;
right: 0;
left: 0;
}
/*
* Sizes
*/

View File

@ -4,6 +4,8 @@ import ReactDOM from 'react-dom';
import classNames from 'classnames';
import elementClass from 'element-class';
import getUniqueElememtId from 'Utilities/getUniqueElementId';
import { isIOS } from 'Utilities/mobile';
import { setScrollLock } from 'Utilities/scrollLock';
import * as keyCodes from 'Utilities/Constants/keyCodes';
import { sizes } from 'Helpers/Props';
import ErrorBoundary from 'Components/Error/ErrorBoundary';
@ -69,7 +71,14 @@ class Modal extends Component {
window.addEventListener('keydown', this.onKeyDown);
if (openModals.length === 1) {
elementClass(document.body).add(styles.modalOpen);
if (isIOS()) {
setScrollLock(true);
const offset = document.body.scrollTop;
document.body.style.top = `${offset * -1}px`;
elementClass(document.body).add(styles.modalOpenIOS);
} else {
elementClass(document.body).add(styles.modalOpen);
}
}
}
@ -78,7 +87,15 @@ class Modal extends Component {
window.removeEventListener('keydown', this.onKeyDown);
if (openModals.length === 0) {
elementClass(document.body).remove(styles.modalOpen);
setScrollLock(false);
if (isIOS()) {
const offset = parseInt(document.body.style.top);
elementClass(document.body).remove(styles.modalOpenIOS);
document.body.scrollTop = (offset * -1);
} else {
elementClass(document.body).remove(styles.modalOpen);
}
}
}

View File

@ -1,5 +1,6 @@
import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { isLocked } from 'Utilities/scrollLock';
import { scrollDirections } from 'Helpers/Props';
import OverlayScroller from 'Components/Scroller/OverlayScroller';
import Scroller from 'Components/Scroller/Scroller';
@ -7,6 +8,17 @@ import styles from './PageContentBody.css';
class PageContentBody extends Component {
//
// Listeners
onScroll = (props) => {
const { onScroll } = this.props;
if (this.props.onScroll && !isLocked()) {
onScroll(props);
}
}
//
// Render
@ -27,6 +39,7 @@ class PageContentBody extends Component {
className={className}
scrollDirection={scrollDirections.VERTICAL}
{...otherProps}
onScroll={this.onScroll}
>
<div className={innerClassName}>
{children}
@ -41,6 +54,7 @@ PageContentBody.propTypes = {
innerClassName: PropTypes.string,
isSmallScreen: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired,
onScroll: PropTypes.func,
dispatch: PropTypes.func
};

View File

@ -2,6 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { WindowScroller } from 'react-virtualized';
import { isLocked } from 'Utilities/scrollLock';
import { scrollDirections } from 'Helpers/Props';
import Measure from 'Components/Measure';
import Scroller from 'Components/Scroller/Scroller';
@ -83,6 +84,16 @@ class VirtualTable extends Component {
}
}
onScroll = (props) => {
if (isLocked()) {
return;
}
const { onScroll } = this.props;
onScroll(props);
}
//
// Render
@ -107,7 +118,7 @@ class VirtualTable extends Component {
<Measure onMeasure={this.onMeasure}>
<WindowScroller
scrollElement={isSmallScreen ? undefined : this._contentBodyNode}
onScroll={onScroll}
onScroll={this.onScroll}
>
{({ height, isScrolling }) => {
return (

View File

@ -2,7 +2,7 @@ import PropTypes from 'prop-types';
import React, { Component } from 'react';
import { Manager, Popper, Reference } from 'react-popper';
import classNames from 'classnames';
import isMobileUtil from 'Utilities/isMobile';
import { isMobile as isMobileUtil } from 'Utilities/mobile';
import { kinds, tooltipPositions } from 'Helpers/Props';
import Portal from 'Components/Portal';
import styles from './Tooltip.css';

View File

@ -1,7 +0,0 @@
import MobileDetect from 'mobile-detect';
export default function isMobile() {
const mobileDetect = new MobileDetect(window.navigator.userAgent);
return mobileDetect.mobile() != null;
}

View File

@ -0,0 +1,12 @@
import MobileDetect from 'mobile-detect';
const mobileDetect = new MobileDetect(window.navigator.userAgent);
export function isMobile() {
return mobileDetect.mobile() != null;
}
export function isIOS() {
return mobileDetect.is('iOS');
}

View File

@ -0,0 +1,13 @@
// Allow iOS devices to disable scrolling of the body/virtual table
// when a modal is open. This will prevent focusing an input in a
// modal causing the modal to close due to scrolling.
let scrollLock = false;
export function isLocked() {
return scrollLock;
}
export function setScrollLock(locked) {
scrollLock = locked;
}