Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update app modal design refactor #1973

Merged

Conversation

SameeraMadushan
Copy link
Contributor

@SameeraMadushan SameeraMadushan commented Mar 22, 2021

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

borderRadius: 12,
overflow: 'hidden',
width: isSmallScreenWidth ? '90%' : windowWidth * 0.3,
Copy link
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
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.

Copy link
Contributor

@roryabraham roryabraham left a comment

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.

@@ -33,31 +35,42 @@ class BaseUpdateAppModal extends PureComponent {
onSubmit={this.submitAndClose}
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
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
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
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
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
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 ?

Copy link
Contributor Author

@SameeraMadushan SameeraMadushan Mar 22, 2021

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
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
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
Copy link
Contributor

roryabraham commented Mar 22, 2021

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.

Copy link
Contributor

@roryabraham roryabraham left a comment

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

src/components/ConfirmModal/index.js Outdated Show resolved Hide resolved
src/components/ConfirmModal/index.js Outdated Show resolved Hide resolved
src/components/ConfirmModal/index.js Outdated Show resolved Hide resolved
src/components/ConfirmModal/index.js Outdated Show resolved Hide resolved
src/components/ConfirmModal/index.js Outdated Show resolved Hide resolved
roryabraham
roryabraham previously approved these changes Mar 22, 2021
Copy link
Contributor

@roryabraham roryabraham left a comment

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
Contributor Author

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

@SameeraMadushan
Copy link
Contributor Author

New screenshots with PR changes

Web

image

Mobile Web

image

Desktop

image

iOS

image

Android

image

@shawnborton
Copy link
Contributor

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

@SameeraMadushan
Copy link
Contributor Author

@shawnborton PR comment updated with latest screenshots.

<Header title={props.title} />
</View>

<Text style={[styles.textLabel, styles.mt4]}>
Copy link
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
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.

style={[
styles.buttonText,
styles.buttonSuccessText,
styles.buttonConfirmText,
Copy link
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
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
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
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
Copy link
Contributor

@Jag96 Jag96 left a comment

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
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
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
Contributor

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

@roryabraham
Copy link
Contributor

We'll also need to upgrade to react 17

@SameeraMadushan
Copy link
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
Contributor

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

@Jag96
Copy link
Contributor

Jag96 commented Mar 23, 2021

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
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
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

@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
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