Expensify / App

Welcome to New Expensify: a complete re-imagination of financial collaboration, centered around chat. Help us build the next generation of Expensify by sharing feedback and contributing to the code.
https://new.expensify.com
MIT License
3.55k stars 2.89k forks source link

[HOLD for payment 2023-06-01] [HOLD PR#16052][$4000] Tooltip doesn't disappear while page is scrolling #15757

Closed kavimuru closed 1 year ago

kavimuru commented 1 year ago

If you haven’t already, check out our contributing guidelines for onboarding and email contributors@expensify.com to request to join our Slack channel!


Action Performed:

  1. Login with any account.
  2. Go to any report that has a lots of request, click on one of those request to open Detail Page.
  3. Try to hover the user name to see the tooltip, after that scroll the page.
  4. Notice that tooltip doesn't disappear while page is scrolling.

Expected Result:

Tooltip should disappear while page is scrolling.

Actual Result:

Tooltip doesn't disappear while page is scrolling.

Workaround:

unknown

Platforms:

Which of our officially supported platforms is this issue occurring on?

Version Number: 1.2.80-1 Reproducible in staging?: y Reproducible in production?: y If this was caught during regression testing, add the test name, ID and link from TestRail: Email or phone of affected tester (no customers): Logs: https://stackoverflow.com/c/expensify/questions/4856 Notes/Photos/Videos:

https://user-images.githubusercontent.com/43996225/223875450-fc035282-c95f-43fd-93fa-48033fc6c352.mp4

https://user-images.githubusercontent.com/43996225/223875464-e402dcf5-59f0-4d30-8150-066cc9c97df8.mov

Expensify/Expensify Issue URL: Issue reported by: @hungvu193 Slack conversation: https://expensify.slack.com/archives/C049HHMV9SM/p1678296752620849

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~019546d7509b0c8a21
  • Upwork Job ID: 1636029730419101696
  • Last Price Increase: 2023-03-30
0xmiros commented 1 year ago

@getusha I don't think your video has issue. The issue is that InvertedFlatList still doesn't work on Safari.

isabelastisser commented 1 year ago

@0xmiroslav did you choose a final proposal? Please let me know so that we can get @yuwenmemon 's review and I can hire the contributors in Upwork. Thanks!

MelvinBot commented 1 year ago

@yuwenmemon @isabelastisser @0xmiroslav this issue is now 3 weeks old. There is one more week left before this issue breaks WAQ and will need to go internal. What needs to happen to get a PR in review this week? Please create a thread in #expensify-open-source to discuss. Thanks!

Litande commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Toolt doesn't disappera while page is scrolling

What is the root cause of that problem?

The issue here is quite similar to 15229 The initial tooltip hover trigger a shared TooltipSense which changes tooltip behavior to appear imidiatly those scrolling displayes other tooltip imidiatly when you scroll over them, the position calcalation is global and those the tooltip stay's behind.

What changes do you think we should make in order to solve the problem?

Similar to a the proposal in https://github.com/Expensify/App/issues/15229#issuecomment-1481037962

  1. Extend TooltipSense component to have method called deactivateImidiate which will reset shared active state of the tooltips.
  2. In TooltipSense to add a listener on window to call deactivateImidiate upon wheel movement. this will effectly will take the make sure that upon scrolling a tooltip will be trigger on the current delayed behavior.

function deactivateImidiate() { active = false; debouncedDeactivate.cancel(); }

window.addEventListener('wheel', () => { deactivateImidiate(); });


As you can see here.

https://user-images.githubusercontent.com/13526647/228641417-cfa37f65-68bb-4ac1-b716-73a623ce75e8.mp4

### What alternative solutions did you explore? (Optional)
cubuspl42 commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

The tooltip doesn't consistently stay on top of the element it's meant to describe, instead remaining in a fixed position relative to the initial cursor interaction.

What is the root cause of that problem?

The tooltip's position is determined once, upon its initial display, and is then fixed in place using CSS.

What changes do you think we should make in order to solve the problem?

To address this issue, we need to ensure the tooltip stays on top of the element it describes.

After thorough exploration, I found a reliable and efficient solution using a polyfill for a new observer called BoundingClientRectObserver, which was inspired by the family of *Observer APIs. I filed a proposal to WHATWG to add it to the Living Standard. This polyfill relies on MutationObserver and ResizeObserver, and its implementation is straightforward. I published this polyfill on NPM.

For React integration, I created a wrapper package.

I propose using this observer to replace our existing tooltip positioning logic. This change simplifies our code and is easy to apply.

The core change:

Tooltip/index.js:

class Tooltip extends PureComponent {
    // ...

    updateBounds(bounds) {
        this.setState({
            wrapperWidth: bounds.width,
            wrapperHeight: bounds.height,
            xOffset: bounds.x,
            yOffset: bounds.y,
        });
    }

    render() {
        // ...

        let child = (
            <BoundsObserver
                activate={this.state.isVisible}
                onBoundsChange={this.updateBounds}
            >
                <View
                    ref={el => this.wrapperView = el}
                    onBlur={this.hideTooltip}
                    focusable={this.props.focusable}
                    style={this.props.containerStyles}
                >

                    {this.props.children}
                </View>
            </BoundsObserver>
        );

        // ...
    }

    // ...
}

This solution offers near-zero delay in updating tooltip positions during animations and scrolling, as demonstrated in the provided video previews. This proves that our approach effectively addresses the original problem.

Animation (https://github.com/Expensify/App/issues/15229)

https://user-images.githubusercontent.com/2590174/229460287-5268e8de-8107-40ce-afa7-9a0e4e10229e.mp4

Scrolling (https://github.com/Expensify/App/issues/15757)

https://user-images.githubusercontent.com/2590174/229460315-f3026356-4dfc-4b85-a240-25528a4e2243.mp4

0xmiros commented 1 year ago

@cubuspl42 I see 2 full proposals in 2 separate comments. Please remove deprecated one. And as a proposal update, update existing comment and post new comment with "Proposal updated"

cubuspl42 commented 1 year ago

@0xmiroslav Done, I removed the deprecated proposal as you suggested

Edit: I'm not sure if I got this right this time, as now I figured out that that's a formal process. I'll do it by the book next time.

0xmiros commented 1 year ago

still evaluating proposals

MelvinBot commented 1 year ago

@yuwenmemon @isabelastisser @0xmiroslav this issue is now 4 weeks old and preventing us from maintaining WAQ, can you:

Thanks!

MelvinBot commented 1 year ago

Current assignee @0xmiroslav is eligible for the Internal assigner, not assigning anyone new.

yuwenmemon commented 1 year ago

Talked with @0xmiroslav - we're going to pick a proposal soon.

0xmiros commented 1 year ago

@cubuspl42 @Litande @getusha @soumyajit4419 @usenbekov Please share video of your solutions like I shared. Especially, I wanna check these behaviors while keep scrolling:

https://user-images.githubusercontent.com/97473779/230607424-9b2e56e7-628e-4ff3-81e5-5a5e66907e4c.mov

cubuspl42 commented 1 year ago

@0xmiroslav While it may be something silly, I have trouble producing an avatar with a workspace indicator. I haven't tested inter-account interactions before, and I'm stuck at the invitation step.

Nevermind, I hacked my way around it.

https://user-images.githubusercontent.com/2590174/230625458-89e468c0-4753-4ca0-a518-0bdde8864291.mov

MelvinBot commented 1 year ago

Triggered auto assignment to @anmurali (External), see https://stackoverflow.com/c/expensify/questions/8582 for more details.

MelvinBot commented 1 year ago

Current assignee @0xmiroslav is eligible for the External assigner, not assigning anyone new.

MelvinBot commented 1 year ago

Current assignee @yuwenmemon is eligible for the External assigner, not assigning anyone new.

yuwenmemon commented 1 year ago

Placing a HOLD on this because the tooltip is getting refactored in https://github.com/Expensify/App/pull/16052

wildan-m commented 1 year ago

Proposal

Please re-state the problem that we are trying to solve in this issue.

Tooltip doesn't disappear while page is scrolling

What is the root cause of that problem?

onMouseLeave event is not always triggered if we move the mouse fast or the DOM is dynamically added or during scrolling, especially if the hover event is inside an expensive tree.

Proof:

https://user-images.githubusercontent.com/11847279/230703132-6cf077ac-d79c-4be5-bdec-90b3cbe0099a.mp4

Proof link: https://codesandbox.io/s/cool-grass-xm7v16?file=/src/App.js

What changes do you think we should make in order to solve the problem?

In our Hoverable component, we add a scroll event listener to the document object and check if the scroll event target is contained by one of our elements. If not currently hovered and element contains event target, set isHovered true, and if currently hovered and the element does not contain event target, set isHovered false.

 checkHover = e => {
        if (this.wrapperView) {
          const { isHovered } = this.state;
          const mouseOver = this.wrapperView.contains(e.target);
          if (!isHovered && mouseOver) {
            this.setIsHovered(true);
          }

          if (isHovered && !mouseOver) {
            this.setIsHovered(false);
          }
        }
    };

I think this is a generic solution. This issue is similar to #16850 but it requires a different event. with the same check function, we can use scroll event for #15757 and mouseover event for #16850

Result

https://user-images.githubusercontent.com/11847279/230706330-83a09f0f-bfc9-4001-acb6-3bd782a291bf.mp4

What alternative solutions did you explore? (Optional)

N/A

MelvinBot commented 1 year ago

📣 @wildan-m! 📣

Hey, it seems we don’t have your contributor details yet! You'll only have to do this once, and this is how we'll hire you on Upwork. Please follow these steps:

  1. Get the email address used to login to your Expensify account. If you don't already have an Expensify account, create one here. If you have multiple accounts (e.g. one for testing), please use your main account email.
  2. Get the link to your Upwork profile. It's necessary because we only pay via Upwork. You can access it by logging in, and then clicking on your name. It'll look like this. If you don't already have an account, sign up for one here.
  3. Copy the format below and paste it in a comment on this issue. Replace the placeholder text with your actual details.

Screen Shot 2022-11-16 at 4 42 54 PM

Format:

Contributor details
Your Expensify account email: <REPLACE EMAIL HERE>
Upwork Profile Link: <REPLACE LINK HERE>
MelvinBot commented 1 year ago

⚠️ Missing/invalid email or upwork profile link. Please make sure you add both your Expensify email and Upwork profile link in the format specified.

MelvinBot commented 1 year ago

⚠️ Missing/invalid email or upwork profile link. Please make sure you add both your Expensify email and Upwork profile link in the format specified.

wildan-m commented 1 year ago

⚠️ Missing/invalid email or upwork profile link. Please make sure you add both your Expensify email and Upwork profile link in the format specified.

Always failed to register my details, who can help with this error?

isabelastisser commented 1 year ago

Not overdue, on hold!

MelvinBot commented 1 year ago

✅ Contributor details stored successfully. Thank you for contributing to Expensify!

isabelastisser commented 1 year ago

not overdue, on hold!

isabelastisser commented 1 year ago

Still on hold!

isabelastisser commented 1 year ago

Not overdue, still on hold!

isabelastisser commented 1 year ago

Not overdue, on hold!

melvin-bot[bot] commented 1 year ago

Reviewing label has been removed, please complete the "BugZero Checklist".

melvin-bot[bot] commented 1 year ago

The solution for this issue has been :rocket: deployed to production :rocket: in version 1.3.17-5 and is now subject to a 7-day regression period :calendar:. Here is the list of pull requests that resolve this issue:

If no regressions arise, payment will be issued on 2023-06-01. :confetti_ball:

After the hold period is over and BZ checklist items are completed, please complete any of the applicable payments for this issue, and check them off once done.

As a reminder, here are the bonuses/penalties that should be applied for any External issue:

melvin-bot[bot] commented 1 year ago

BugZero Checklist: The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed:

isabelastisser commented 1 year ago

@yuwenmemon @0xmiroslav I see the awaiting payment label, but reading through this long issue, I can't confirm that we picked a proposal. Can you please guide me on the next steps here? Thanks!

0xmiros commented 1 year ago

@isabelastisser The PR which fixes https://github.com/Expensify/App/issues/15229 also fixed this one. As no one assigned here, we can just close. Just one thing: May I request partial compensation as I reviewed initial proposals (as you see long comments history) as per C+ doc?

isabelastisser commented 1 year ago

Hi @0xmiroslav, thanks for clarifying! I've sent you an offer in Upwork, please accept it, and I will process a partial payment for your review to multiple proposals. Thanks!

We're all set!

0xmiros commented 1 year ago

@isabelastisser accepted, thanks!

cubuspl42 commented 1 year ago

@yuwenmemon @flodnv @0xmiroslav

I'd like to ask for clarification of the process for handling PRs that solve more than one issue, as they don't happen often. In my case, I've proposed a solution that deals with two different issues (check my proposal here). I made sure to create a solution that intentionally addresses both issues.

Per the guidelines, I linked both issues in the PR, and this was acknowledged by @flodnv. The automatic system also recognized this.

I believe that offering a single bounty for a PR that explicitly solves multiple issues could encourage contributors to focus on localized separate solutions instead of more comprehensive ones. This might not be the best approach for the project from a broader perspective.

0xmiros commented 1 year ago

@cubuspl42 there's no guideline about that. If you claim more bounty in such cases, please raise discussion on slack. This closed issue seems not a good place to have such discussions.

cubuspl42 commented 1 year ago

@0xmiroslav I can't see why this is a bad place for this clarification, as if there's no guideline, there's no obvious reason to close the [HOLD for payment] issue without a payment or a clarification of the process. Still, I'll respect your request and will post this on Slack.

getusha commented 1 year ago

@cubuspl42 as far as i know payment will be issued for the issue that you proposed a solution for, i have seen multiple instances.

flodnv commented 1 year ago

Discussed here https://expensify.slack.com/archives/C01GTK53T8Q/p1685711548218919

@isabelastisser please issue $4000 payment to @cubuspl42 for fixing this bug, if it hasn't yet been done.