Skip to content

Commit

Permalink
Merge pull request #12848 from Expensify/tgolen-fix-signin-keyboard-a…
Browse files Browse the repository at this point in the history
…voiding

Fix the keyboard overlapping buttons on the sign in form
  • Loading branch information
tgolen authored Dec 5, 2022
2 parents b48ded2 + bbba5e5 commit 5530ea2
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 121 deletions.
2 changes: 1 addition & 1 deletion src/components/FormAlertWithSubmitButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const defaultProps = {

const FormAlertWithSubmitButton = props => (
<FormAlertWrapper
containerStyles={[styles.mh5, styles.mb5, styles.flex1, styles.justifyContentEnd, ...props.containerStyles]}
containerStyles={[styles.mh5, styles.mb5, styles.justifyContentEnd, ...props.containerStyles]}
isAlertVisible={props.isAlertVisible}
isMessageHtml={props.isMessageHtml}
message={props.message}
Expand Down
7 changes: 7 additions & 0 deletions src/components/withWindowDimensions.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ const windowDimensionsPropTypes = {

// Is the window width narrow, like on a tablet device?
isMediumScreenWidth: PropTypes.bool.isRequired,

// Is the window width wide, like on a browser or desktop?
isLargeScreenWidth: PropTypes.bool.isRequired,
};

const windowDimensionsProviderPropTypes = {
Expand All @@ -35,6 +38,7 @@ class WindowDimensionsProvider extends React.Component {
const isSmallScreenWidth = initialDimensions.width <= variables.mobileResponsiveWidthBreakpoint;
const isMediumScreenWidth = initialDimensions.width > variables.mobileResponsiveWidthBreakpoint
&& initialDimensions.width <= variables.tabletResponsiveWidthBreakpoint;
const isLargeScreenWidth = !isSmallScreenWidth && !isMediumScreenWidth;

this.dimensionsEventListener = null;

Expand All @@ -43,6 +47,7 @@ class WindowDimensionsProvider extends React.Component {
windowWidth: initialDimensions.width,
isSmallScreenWidth,
isMediumScreenWidth,
isLargeScreenWidth,
};
}

Expand All @@ -67,11 +72,13 @@ class WindowDimensionsProvider extends React.Component {
const {window} = newDimensions;
const isSmallScreenWidth = window.width <= variables.mobileResponsiveWidthBreakpoint;
const isMediumScreenWidth = !isSmallScreenWidth && window.width <= variables.tabletResponsiveWidthBreakpoint;
const isLargeScreenWidth = !isSmallScreenWidth && !isMediumScreenWidth;
this.setState({
windowHeight: window.height,
windowWidth: window.width,
isSmallScreenWidth,
isMediumScreenWidth,
isLargeScreenWidth,
});
}

Expand Down
2 changes: 1 addition & 1 deletion src/pages/signin/ResendValidationForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const ResendValidationForm = (props) => {
{!_.isEmpty(props.account.message) && (

// DotIndicatorMessage mostly expects onyxData errors so we need to mock an object so that the messages looks similar to prop.account.errors
<DotIndicatorMessage style={[styles.mb5]} type="success" messages={{0: props.account.message}} />
<DotIndicatorMessage style={[styles.mb5, styles.flex0]} type="success" messages={{0: props.account.message}} />
)}
{!_.isEmpty(props.account.errors) && (
<DotIndicatorMessage style={[styles.mb5]} type="error" messages={props.account.errors} />
Expand Down
114 changes: 49 additions & 65 deletions src/pages/signin/SignInPageLayout/SignInPageContent.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import React from 'react';
import {ScrollView, View} from 'react-native';
import {View, TouchableWithoutFeedback, Keyboard} from 'react-native';
import PropTypes from 'prop-types';
import {withSafeAreaInsets} from 'react-native-safe-area-context';
import styles from '../../../styles/styles';
import variables from '../../../styles/variables';
import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView';
import ExpensifyCashLogo from '../../../components/ExpensifyCashLogo';
import Text from '../../../components/Text';
import TermsAndLicenses from '../TermsAndLicenses';
import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize';
import SignInPageForm from '../../../components/SignInPageForm';
import compose from '../../../libs/compose';
import scrollViewContentContainerStyles from './signInPageStyles';
import withKeyboardState from '../../../components/withKeyboardState';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import * as StyleUtils from '../../../styles/StyleUtils';

const propTypes = {
/** The children to show inside the layout */
Expand All @@ -31,71 +28,58 @@ const propTypes = {
...windowDimensionsPropTypes,
};

const SignInPageContent = props => (
<ScrollView
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
style={[
styles.h100,
!props.isSmallScreenWidth && styles.alignSelfCenter,
!props.isSmallScreenWidth && styles.signInPageWideLeftContainer,
]}
contentContainerStyle={[
scrollViewContentContainerStyles,
styles.alignItemsCenter,
!props.isSmallScreenWidth && styles.ph6,
]}
>
<View style={[styles.flex1, styles.flexRow]}>
<View style={[
styles.flex1,
styles.signInPageNarrowContentContainer,
]}
>
<SignInPageForm style={[
const SignInPageContent = (props) => {
const dismissKeyboardWhenTappedOutsideOfInput = () => {
// This prop comes from withKeyboardState
if (!props.isShown) {
return;
}
Keyboard.dismiss();
};

return (
<TouchableWithoutFeedback onPress={dismissKeyboardWhenTappedOutsideOfInput}>
<View
style={[
styles.flex1,
styles.alignSelfStretch,
props.isSmallScreenWidth ? styles.ph5 : styles.ph4,
styles.signInPageLeftContainer,
!props.isSmallScreenWidth && styles.signInPageLeftContainerWide,
]}
>
<KeyboardAvoidingView
behavior="position"
style={[
StyleUtils.getModalPaddingStyles({
shouldAddBottomSafeAreaPadding: true,
modalContainerStylePaddingBottom: 20,
safeAreaPaddingBottom: props.insets.bottom,
}),
props.isSmallScreenWidth ? styles.signInPageNarrowContentMargin : {},
!props.isMediumScreenWidth || (props.isMediumScreenWidth && props.windowHeight < variables.minHeightToShowGraphics) ? styles.signInPageWideLeftContentMargin : {},
styles.mb3,
]}
>
<View style={[
styles.componentHeightLarge,
...(props.isSmallScreenWidth ? [styles.mb2] : [styles.mt6, styles.mb5]),
]}
>
<ExpensifyCashLogo
width={variables.componentSizeLarge}
height={variables.componentSizeLarge}
/>
</View>
{props.shouldShowWelcomeText && (
<Text style={[styles.mv5, styles.textLabel, styles.h3]}>
{props.welcomeText}
</Text>
)}
{props.children}
</KeyboardAvoidingView>
</SignInPageForm>
<View style={[styles.mb5, styles.alignSelfCenter, styles.ph5]}>
<TermsAndLicenses />
>
<View style={[styles.flex1, styles.alignSelfCenter, styles.signInPageWelcomeFormContainer]}>
{/* This empty view creates margin on the top of the sign in form which will shrink and grow depending on if the keyboard is open or not */}
<View style={[styles.flexGrow1, styles.signInPageContentTopSpacer]} />

<View style={[styles.flexGrow2]}>
<SignInPageForm style={[styles.alignSelfStretch]}>
<View style={[
styles.componentHeightLarge,
...(props.isSmallScreenWidth ? [styles.mb2] : [styles.mt6, styles.mb5]),
]}
>
<ExpensifyCashLogo
width={variables.componentSizeLarge}
height={variables.componentSizeLarge}
/>
</View>
{props.shouldShowWelcomeText && (
<View style={[styles.signInPageWelcomeTextContainer]}>
<Text style={[styles.mv5, styles.textLabel, styles.h3]}>
{props.welcomeText}
</Text>
</View>
)}
{props.children}
</SignInPageForm>
</View>
<View style={[styles.mv5]}>
<TermsAndLicenses />
</View>
</View>
</View>
</View>
</ScrollView>
);
</TouchableWithoutFeedback>
);
};

SignInPageContent.propTypes = propTypes;
SignInPageContent.displayName = 'SignInPageContent';
Expand Down
11 changes: 1 addition & 10 deletions src/pages/signin/SignInPageLayout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
import SignInPageContent from './SignInPageContent';
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions';
import styles from '../../../styles/styles';
import variables from '../../../styles/variables';
import SignInPageGraphics from './SignInPageGraphics';

const propTypes = {
Expand All @@ -25,29 +24,21 @@ const SignInPageLayout = (props) => {
let containerStyles = [styles.flex1, styles.signInPageInner];
let contentContainerStyles = [styles.flex1, styles.flexRow];

const isLongMediumScreenWidth = props.isMediumScreenWidth && props.windowHeight >= variables.minHeightToShowGraphics;

if (props.isSmallScreenWidth) {
containerStyles = [styles.flex1];
contentContainerStyles = [styles.flex1];
} else if (isLongMediumScreenWidth) {
containerStyles = [styles.dFlex, styles.signInPageInner, styles.flexColumnReverse, styles.justifyContentBetween];
contentContainerStyles = [styles.flex1];
}

return (
<View style={containerStyles}>
{isLongMediumScreenWidth && (
<SignInPageGraphics />
)}
<View style={contentContainerStyles}>
<SignInPageContent
welcomeText={props.welcomeText}
shouldShowWelcomeText={props.shouldShowWelcomeText}
>
{props.children}
</SignInPageContent>
{!props.isSmallScreenWidth && !isLongMediumScreenWidth && (
{!props.isSmallScreenWidth && (
<SignInPageGraphics />
)}
</View>
Expand Down
51 changes: 12 additions & 39 deletions src/styles/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,60 +898,33 @@ const styles = {
flex: 1,
},

signInPageLogo: {
height: variables.componentSizeLarge,
marginBottom: 24,
},

signInPageInner: {
marginLeft: 'auto',
marginRight: 'auto',
height: '100%',
width: '100%',
},

signInPageInnerNative: {
width: '100%',
},

signInPageHeroHeading: {
fontFamily: fontFamily.EXP_NEUE,
fontWeight: fontWeightBold,
fontSize: variables.fontSizeHero,
color: themeColors.appBG,
lineHeight: variables.lineHeightHero,
},

signInPageHeroDescription: {
fontFamily: fontFamily.EXP_NEUE,
fontSize: variables.fontSizeNormal,
color: themeColors.appBG,
},

signInPageFormContainer: {
maxWidth: 295,
width: '100%',
},

signInPageNarrowContentContainer: {
maxWidth: 335,
signInPageContentTopSpacer: {
maxHeight: 132,
minHeight: 24,
},

signInPageNarrowContentMargin: {
marginTop: '40%',
signInPageLeftContainer: {
paddingLeft: 40,
paddingRight: 40,
},

signInPageWideLeftContainer: {
width: 375,
maxWidth: 375,
signInPageLeftContainerWide: {
maxWidth: 360,
},

signInPageWideLeftContentMargin: {
marginTop: '44.5%',
signInPageWelcomeFormContainer: {
maxWidth: 300,
},

signInPageWideHeroContent: {
maxWidth: 400,
signInPageWelcomeTextContainer: {
width: 300,
},

changeExpensifyLoginLinkContainer: {
Expand Down
8 changes: 4 additions & 4 deletions src/styles/utilities/flex.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,6 @@ export default {
flexDirection: 'column',
},

flexColumnReverse: {
flexDirection: 'column-reverse',
},

justifyContentCenter: {
justifyContent: 'center',
},
Expand Down Expand Up @@ -108,6 +104,10 @@ export default {
flexGrow: 1,
},

flexGrow2: {
flexGrow: 2,
},

flexGrow4: {
flexGrow: 4,
},
Expand Down
1 change: 0 additions & 1 deletion src/styles/variables.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ export default {
tooltipzIndex: 10050,
gutterWidth: 16,
popoverMenuShadow: '0px 4px 12px 0px rgba(0, 0, 0, 0.06)',
minHeightToShowGraphics: 854, // Login form layout breaks below this height due to insufficient space to show the form and graphics
optionRowHeight: 64,
optionRowHeightCompact: 52,
optionsListSectionHeaderHeight: getValueUsingPixelRatio(54, 60),
Expand Down

0 comments on commit 5530ea2

Please sign in to comment.