-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Try to refactor the logic regarding refocusing when the modal is closed #29199
Conversation
Hey! I see that you made changes to our Form component. Make sure to update the docs in FORMS.md accordingly. Cheers! |
1130e78
to
d5694f6
Compare
ec72ddf
to
05c51f6
Compare
Hi @0xmiroslav, when you get a chance, could you take a quick look at the implementation of this PR? It has successfully passed tests in many scenarios. I'm eager to get your initial impressions on this PR, such as whether this implementation approach is acceptable and if there are any serious blockers I might have overlooked. :) |
> | ||
{props.children} | ||
</View> | ||
<ModalContent onDismiss={handleDismissContent}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the purpose of this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
App/src/components/PopoverWithoutOverlay/index.js
Lines 84 to 88 in e1fcb42
} else { | |
props.onModalHide(); | |
close(props.anchorRef); | |
Modal.onModalDidClose(); | |
} |
It's somewhat similar to the above condition code, but has the following advantages:
- it's only called when the modal disappears (the code above is called even on the initial load),
- it's beneficial for extracting common logic in the future.
src/pages/iou/WaypointEditor.js
Outdated
@@ -153,6 +154,7 @@ function WaypointEditor({route: {params: {iouType = '', transactionID = '', wayp | |||
}; | |||
|
|||
const deleteStopAndHideModal = () => { | |||
setRestoreFocusType(CONST.MODAL.RESTORE_TYPE.DELETE); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the focus type have to change dynamically?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this case, when we remove a waypoint, the navigation will return to the distance page, the input is unmounted after refocusing is called, which can cause keyboard flickering. So setting the type to DELETE
can avoid this issue. When clicking Cancel
, we can set it back to DEFAULT
to allow refocusing to continue working.
demo.mp4
I will take a deeper dive into this PR starting tomorrow. |
Hey both, just checking the progress here. It looks like there have been a decent amount of updates since the last review, but I see lint errors. @ntdiary is this ready for a second C+ review? |
@Julesssss, so far, the current implementation has fixed many cases. My updates are more aimed at resolving conflicts. |
Just updated the test cases, so far, the count is 23. :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @ntdiary, I didn't realise this would require so many test cases. Lets talk in the issue about increasing the bounty 👍
Yeah, I think the bounty should be increased for sure. Meanwhile, we should create a project and put other focus-related issues on hold so that we don't create new challenges for this PR. May be inform this on the C+ channel so that C+ can prevent that from happening. |
Hey @parasharrajat, bumping the review here now your back |
I thought we are breaking this PR into parts. @ntdiary Could you please confirm? |
@ntdiary can you provide an update on where we're at here? |
@mallenexpensify, yesterday, @getusha reported two bugs in the first small PR #35572, and I'm still investigating them. :) |
Hey @ntdiary, just checking in here for the next steps as the linked PRs were merged. |
@Julesssss, sorry for the delayed update. While I have reassigned all other new issues in the past few weeks, there are still two long-standing and relatively challenging issues that require my attention (#26239, #37596). Now that progress has been made on the other two issues, so expect to be able to raise a second small PR for this issue this week. 😂 |
Ah another new problem introduced by the new architecture 😅 |
Hey @ntdiary. Can we close this outdated PR? |
@Julesssss, sure! BTW, I noticed that some issues have been put on hold because of this PR, so I plan to look into them this week to see if I can offer any suggestions, just like issue #31224. :) |
So far, the
Modal
components under our control can be categorized into three types:BaseModal
,PopoverWithoutOverlay
, andRHP
(Right Hand Panel).This PR will simulate the iOS native Modal refocusing behavior: If there is a focused input field before opening the
Modal
, our app will attempt to restore that focus after theModal
is dismissed. If there is no focus before opening, no restore after theModal
is dismissed.Additionally, this PR will introduce a
restoreFocusType
prop, here are possible values:default
, this will follow the default behavior mentioned above.preserve
, this will leave the focus in the manager and no longer restore focus, applicable for consecutive modal scenarios.delete
, this will delete the focus and no longer restore focus, the caller can decide in its own business logic whether to focus a specific element.The specific business Modals that have been tested:
delete
actions will show this modal)Once the POC is approved by most people, we'll refine the code, clean things up, and then repush it.
Details
Fixed Issues
$ #29011
$ #24452
PROPOSAL: #24452 (comment)
Tests
context menu modal
case 1 (cancel action)
case 2 (add reaction + cancel action)
Add reaction
to open the emoji modal.case 3 (edit coment)
Edit comment
.case 4 (delete comment)
Delete comment
to open theConfirm
modal.Delete
button /Cancel
button to close theConfirm
modal.emoji modal
case 1 (cancel action)
case 2 (cancel action)
case 3 (cancel action)
ios nativemain focus didn't show
Right Hand Panel
case 1 (test by mouse)
case 2 (test by keyboard shortcuts)
CMD + J
to open the keyboard shortcuts page.attachment modal
case 1 (cancel action)
case 2 (first attachment modal + RHP)
Request money
/Send money
/Assign task
.it seems that the viewport api is not stable.
case 3 (all mobile platforms: cancel action for the second modal)
Add attachment
.webdesktopcase 4 (cancel file selection)
Add attachment
.Choose from gallery
/Choose document
.Cancel
to cancel the file selection.case 5 (send an attachment)
Add attachment
.Choose from gallery
.Send
button.case 6 (send an invalid attachment, e.g. file size < 240B)
Add attachment
.Choose document
.Close
button.case 7 (attachment preview modal)
case 8 (receipt preview modal + ThreeDotsMenu modal)
case 9 (receipt preview modal + ThreeDotsMenu modal + RHP)
Replace
option.controlled by
useKeyboardManager
controlled by
useKeyboardManager
ThreeDotsMenu modal
case 1 (cancel action)
case 2 (delete action)
IOU
report.Delete request
to open theConfirm
modal.Cancel
button to close theConfirm
modal.case 3 (waypoint editor, cancel action)
case 4 (waypoint editor, delete option + cancel action)
Delete
option.Cancel
button to close theConfirm
modal.case 5 (waypoint editor, delete option + confirm action)
Delete
option.Delete
button.Offline tests
QA Steps
PR Author Checklist
### Fixed Issues
section aboveTests
sectionOffline steps
sectionQA steps
sectiontoggleReport
and notonIconClick
)myBool && <MyComponent />
.src/languages/*
files and using the translation methodWaiting for Copy
label for a copy review on the original GH to get the correct copy.STYLE.md
) were followedAvatar
, I verified the components usingAvatar
are working as expected)/** comment above it */
this
are necessary to be bound (i.e. avoidthis.submit = this.submit.bind(this);
ifthis.submit
is never passed to a component event handler likeonClick
)StyleUtils.getBackgroundAndBorderStyle(themeColors.componentBG)
)Avatar
is modified, I verified thatAvatar
is working as expected in all cases)ScrollView
component to make it scrollable when more elements are added to the page.main
branch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTest
steps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
MacOS: Desktop