Skip to content

Update app modal design refactor#1973

Merged
Jag96 merged 9 commits into
Expensify:masterfrom
SameeraMadushan:sameera-update-app-modal-refactor
Mar 23, 2021
Merged

Update app modal design refactor#1973
Jag96 merged 9 commits into
Expensify:masterfrom
SameeraMadushan:sameera-update-app-modal-refactor

Conversation

@SameeraMadushan

@SameeraMadushan SameeraMadushan commented Mar 22, 2021

Copy link
Copy Markdown
Contributor

Details

Update modal design modified with adding a new modal type called CONFIRM.
Also HeaderWithCloseButton replaced with the Header component inside BaseUpdateAppModal

Fixed Issues

Fixes #1853

Tests

To view the update modal temporarily you have to set visibility to true. To do that you can do the following.

  • Set this.props.updateAvailable to !this.props.updateAvailable in Expensify.js
  • Otherwise, Wait for an update to be deployed, Observe the modal that appears.

Tested On

  • Web
  • Mobile Web
  • Desktop
  • iOS
  • Android

Screenshots

Web

image

Web - small screen

image

Mobile Web

image

Desktop

image

iOS

image

Android

image

@SameeraMadushan SameeraMadushan requested a review from a team as a code owner March 22, 2021 08:06
@botify botify requested review from Jag96 and removed request for a team March 22, 2021 08:06
Comment thread src/styles/getModalStyles.js Outdated

borderRadius: 12,
overflow: 'hidden',
width: isSmallScreenWidth ? '90%' : windowWidth * 0.3,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to have a fixed width on all non-small screens, so I think just using 375 (the same width as the sidebar) works.

For small screens, I think it makes sense to repeat the bottomDocked modal pattern here where it would look something like:
image

cc @roryabraham

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shawnborton Sure. I'll update the changes.

@roryabraham roryabraham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think of a "confirm" modal as having modal which is sized like the one you have here, but which also:

  1. Does not have an x to close in the header
  2. Has two buttons, one "confirm" button and one "cancel", both of which should close the modal

This is a very common reusable pattern for a modal, so I'd like to see it created as it's own component. You could call it ConfirmModal, and give it props like this:

const propTypes = {
    title: PropTypes.string.isRequired,
    onConfirm: PropTypes.func.isRequired,
    onCancel: PropTypes.func.isRequired,
    confirmText: PropTypes.string,
    cancelText: PropTypes.string,
    prompt: PropTypes.string,
};

const defaultProps = {
    confirmText: 'Yes',
    cancelText: 'No',
    prompt: '',
};

That component would internally use withWindowDimensions, and be BottomDocked on small screens and confirm on wider screens. Then BaseUpdateAppModal can use the ConfirmModal.

onClose={() => this.setState({isModalOpen: false})}
isVisible={this.state.isModalOpen}
type={this.props.isSmallScreenWidth
? CONST.MODAL.MODAL_TYPE.BOTTOM_DOCKED : CONST.MODAL.MODAL_TYPE.CONFIRM}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB typically we format multiline ternaries like this:

const result = condition
    ? valueIfTrue
    : valueIfFalse;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update it.

Update now or restart the app at a later time to download the latest changes.
</Text>
{this.props.onSubmit && (
<View style={[styles.m5]}>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need for square brackets if it's just a single style.

Suggested change
<View style={[styles.m5]}>
<View style={styles.m5}>

</Text>
{this.props.onSubmit && (
<View style={[styles.m5]}>
<View style={[styles.flexRow]}>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
<View style={[styles.flexRow]}>
<View style={styles.flexRow}>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the header need to be wrapped in a view w/ flexRow ?

@SameeraMadushan SameeraMadushan Mar 22, 2021

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because <Header> component does have another view and it has flex1.
In other places <Header> component is used inside a <view> with flexRow.
If I remove flexRow from here it won't show in the mobile app.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, thanks for explaining.

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

I think of a "confirm" modal as having modal which is sized like the one you have here, but which also:

  1. Does not have an x to close in the header
  2. Has two buttons, one "confirm" button and one "cancel", both of which should close the modal

This is a very common reusable pattern for a modal, so I'd like to see it created as it's own component. You could call it ConfirmModal, and give it props like this:

const propTypes = {
    title: PropTypes.string.isRequired,
    onConfirm: PropTypes.func.isRequired,
    onCancel: PropTypes.func.isRequired,
    confirmText: PropTypes.string,
    cancelText: PropTypes.string,
    prompt: PropTypes.string,
};

const defaultProps = {
    confirmText: 'Yes',
    cancelText: 'No',
    prompt: '',
};

That component would internally use withWindowDimensions, and be BottomDocked on small screens and confirm on wider screens. Then BaseUpdateAppModal can use the ConfirmModal.

I will do it accordingly.

But I have few questions.

  1. The modal visibility will be handled inside the ConfirmModal. Is that ok?
  2. Do we need to have onCancel prop? Because we need onCancel only to set the visibility to false right? We can do it inside the ConfirmModal

@roryabraham

roryabraham commented Mar 22, 2021

Copy link
Copy Markdown
Contributor

The modal visibility will be handled inside the ConfirmModal. Is that ok?

Hmmm, this is a bit contrary to how our other modals typically work. We should give ConfirmModal an isVisible prop, and let the parent component manage the visibility via the onConfirm and onCancel props. Sorry I missed the isVisible boolean prop in my change request above.

@roryabraham roryabraham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, just some minor code style comments. Also, since you just have one file in the ConfirmModal module, you don't need it to be a directory. You can just move src/components/ConfirmModal/index.js to src/components/ConfirmModal.js

Comment thread src/components/ConfirmModal/index.js Outdated
Comment thread src/components/ConfirmModal/index.js Outdated
Comment thread src/components/ConfirmModal/index.js Outdated
Comment thread src/components/ConfirmModal/index.js Outdated
Comment thread src/components/ConfirmModal/index.js Outdated
roryabraham
roryabraham previously approved these changes Mar 22, 2021

@roryabraham roryabraham left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks for the quick turnaround. Code looks good. I tested it out a bit too and it seems to work well. However, can you please be sure to retest on all platforms and provide screenshots for @shawnborton to re-review. In my opinion, the font size for the prompt maybe looks a bit small and has maybe too large a top margin, but otherwise all looks good.

image

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

Thanks @roryabraham
I will retest and upload new screenshots for review.

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

New screenshots with PR changes

Web

image

Mobile Web

image

Desktop

image

iOS

image

Android

image

@roryabraham roryabraham requested a review from shawnborton March 22, 2021 20:58
@shawnborton

Copy link
Copy Markdown
Contributor

Could you please update the screenshots in the original comment of this PR?

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

@shawnborton PR comment updated with latest screenshots.

Comment thread src/components/ConfirmModal.js Outdated
<Header title={props.title} />
</View>

<Text style={[styles.textLabel, styles.mt4]}>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use styles.textP here please?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, this is not a blocker but I think I prefer adding margin to the bottom of the modal header as opposed to the top of this text block.

Comment thread src/components/ConfirmModal.js Outdated
style={[
styles.buttonText,
styles.buttonSuccessText,
styles.buttonConfirmText,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does buttonConfirmText do versus buttonSuccessText? I'm not entirely sure why buttonConfirmText exists, it looks like it just adds padding to the left and the right but I actually don't think we need it. I would suggest we remove this.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. styles.buttonConfirmText is for add horizontal padding. Seems we don't need it here. I'll remove it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome, thank you! Changes look good, you'll just need to update the screenshots again.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Screenshots updated.

shawnborton
shawnborton previously approved these changes Mar 23, 2021

@Jag96 Jag96 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On Web when I load the app up, I see that the Cancel button is highlighted with a blue border, is that expected or is there something we can do to remove that?

image

Other than that, looks great!

@roryabraham

Copy link
Copy Markdown
Contributor

Interestingly, I noticed the same thing but didn't comment because the view component doesn't support the focusable prop in react-native-web 14. @SameeraMadushan If you wanted, however, you could update react-native-web to v15, which now supports that prop. https://github.com/necolas/react-native-web/releases/tag/0.15.0

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

Thanks for the suggestion @roryabraham. Setting focusable to false fixed the issue.
I will do the testing and push changes with react-native-web v15.

@roryabraham

Copy link
Copy Markdown
Contributor

Hooray! ....hopefully we don't break anything 😬

@roryabraham

Copy link
Copy Markdown
Contributor

We'll also need to upgrade to react 17

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

We'll also need to upgrade to react 17

Tested with all platforms. It works without any regression.
Is it good to upgrade react independently?

@roryabraham

Copy link
Copy Markdown
Contributor

Well, I just noticed that react 17 is listed as a peer dependency, which makes me more nervous to greenlight this change.

@Jag96

Jag96 commented Mar 23, 2021

Copy link
Copy Markdown
Contributor

Thanks for looking into that! Since it's already a pre-existing issue with our app and it requires updating some libs that would affect all functionality, I suggest we do this in a different PR.

@SameeraMadushan can we revert the update to react-native-web and hold off on updating react to 17 in this PR? We can create a new issue for the blue border and handle it separately.

@SameeraMadushan

Copy link
Copy Markdown
Contributor Author

@roryabraham I see react 17 used in react native 0.64. So it's a bit hard to predict what will happen.
upgrade helper
@Jag96 Can do that.

@roryabraham

Copy link
Copy Markdown
Contributor

Yeah, sorry for the go-around here @SameeraMadushan, let's tackle this later.

@Jag96 Jag96 merged commit c2571b7 into Expensify:master Mar 23, 2021
@isagoico

Copy link
Copy Markdown

@SameeraMadushan Hello! This PR looks like internal QA. If so, can you let me know when it's QA'd in staging so I can check it off the deploy list? Thanks in advance!

@roryabraham

Copy link
Copy Markdown
Contributor

@isagoico, in this case there's really no easy way to QA the issue on staging, so feel free to check it off the deploy list.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Update the UpdateAppModal for easier visibility

5 participants