Skip to content

[HOLD for payment 2025-02-04] [$250] Web - Tooltip - Educational tooltip appears on not here page #55058

Closed

Description

@IuliiaHerets

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


Version Number: 9.0.83-0
Reproducible in staging?: Yes
Reproducible in production?: Yes
If this was caught during regression testing, add the test name, ID and link from TestRail: Exp
Email or phone of affected tester (no customers): joaojjasjaojsi@gmail.com
Issue reported by: Applause Internal Team
Device used: Mac 15.0 / Chrome
App Component: Other

Action Performed:

  1. Go to staging.new.expensify.com
  2. Log in with a new account.
  3. Complete the onboarding.
  4. Open FAB to dismiss the tooltip.
  5. Create a new workspace.
  6. Go back to LHN.
  7. Do not open workspace chat because we need to keep the tooltip untouched.
  8. Go to this link https://staging.new.expensify.com/v/123/456

Expected Result:

Educational tooltip will not appear on not here page.

Actual Result:

Educational tooltip appears on not here page.

Workaround:

Unknown

Platforms:

  • Android: Standalone
  • Android: HybridApp
  • Android: mWeb Chrome
  • iOS: Standalone
  • iOS: HybridApp
  • iOS: mWeb Safari
  • MacOS: Chrome / Safari
  • MacOS: Desktop

Screenshots/Videos

Bug6710702_1736497788719.20250110_162705.mp4

View all open jobs on GitHub

Upwork Automation - Do Not Edit
  • Upwork Job URL: https://www.upwork.com/jobs/~021878843621471358356
  • Upwork Job ID: 1878843621471358356
  • Last Price Increase: 2025-01-20
Issue OwnerCurrent Issue Owner: @Ollyws

Activity

  1. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jan 10, 2025
  2. melvin-bot commented on Jan 10, 2025

    @melvin-bot

    Triggered auto assignment to @RachCHopkins (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  3. bernhardoj commented on Jan 10, 2025

    @bernhardoj
    Contributor

    Proposal

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

    The educational tooltip shows on the validate login page.

    What is the root cause of that problem?

    The tooltip shows if the current active route is home.

    const isActiveRouteHome = useIsCurrentRouteHome();

    const shouldTooltipBeVisible = shouldUseNarrowLayout ? isScreenFocused && isActiveRouteHome : isActiveRouteHome;

    When we open the validate login page, the nav stack looks like: [BottomTab, ValidateLogin]

    useIsCurrentRouteHome gets the state using useNavigationState which gets the state of the current navigator, which is the BottomTabNavigator, so it always return true even though the validate login page covers the whole screen.

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

    There is no hook to listen for root navigator, so I'm thinking to have the same approach as this.

    const modalScreenListeners = {
    focus: () => {
    Modal.setModalVisibility(true);
    },
    blur: () => {
    Modal.setModalVisibility(false);
    },
    beforeRemove: () => {
    Modal.setModalVisibility(false);
    Modal.willAlertModalBecomeVisible(false);
    },
    };

    We will create a new Onyx key called FULLSCREEN_VISIBILITY and set it to true when the validate login page is focused and to false when remove.

    function setVisibility(isVisible: boolean) {
        Onyx.merge(ONYXKEYS.FULLSCREEN_VISIBILITY, isVisible);
    }
    ...
    const fullScreenListeners = {
        focus: () => {
            FullscreenVisibility.setVisibility(true);
        },
        beforeRemove: () => {
            FullscreenVisibility.setVisibility(false);
        },
    };
    

    Then attach the listener here (and other screen if needed)

    <RootStack.Screen
    name={SCREENS.VALIDATE_LOGIN}
    options={{
    ...rootNavigatorOptions.fullScreen,
    headerShown: false,
    title: 'New Expensify',
    }}
    getComponent={loadValidateLoginPage}
    />

    Next, we listen for the onyx in OptionRowLHN.

    const [isFullscreenVisible] = useOnyx(ONYXKEYS.FULLSCREEN_VISIBILITY);
    

    Then, update the visibility logic here to prevent the tooltip from showing when isFullscreenVisible is true.

    const {tooltipToRender, shouldShowTooltip} = useMemo(() => {
    const tooltip = shouldShowGetStartedTooltip ? CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR : CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP;
    const shouldShowTooltips = shouldShowWokspaceChatTooltip || shouldShowGetStartedTooltip;
    const shouldTooltipBeVisible = shouldUseNarrowLayout ? isScreenFocused && isActiveRouteHome : isActiveRouteHome;
    // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
    return {tooltipToRender: tooltip, shouldShowTooltip: shouldShowTooltips && shouldTooltipBeVisible};
    }, [shouldShowGetStartedTooltip, shouldShowWokspaceChatTooltip, isScreenFocused, shouldUseNarrowLayout, isActiveRouteHome]);

    const shouldTooltipBeVisible = shouldUseNarrowLayout ? isScreenFocused && isActiveRouteHome : isActiveRouteHome && !isFullscreenVisible;
    

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    N/A

  4. huult commented on Jan 10, 2025

    @huult
    Contributor

    Edited by proposal-police: This proposal was edited at 2025-01-10 14:21:47 UTC.

    Proposal

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

    Tooltip - Educational tooltip appears on not here page

    What is the root cause of that problem?

    The page showing ‘Not Found’ in this ticket includes the ValidateLogin page and OptionRowLHN inside BottomTabNavigator. When the full-screen ‘Not Found’ view of ValidateLogin is displayed, the condition to trigger the educational tooltip is still executed and returns true, causing the tooltip to appear.

    Screenshot 2025-01-10 at 21 13 55

    const shouldTooltipBeVisible = shouldUseNarrowLayout ? isScreenFocused && isActiveRouteHome : isActiveRouteHome;

    With this issue, any page with the route name ValidateLogin will cause this problem to occur, such as ‘Not Found’ for invalid magic links, ExpiredValidateCodeModal, or JustSignedInModal...

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

    To resolve this issue, we should prevent the educational tooltip from being displayed when the topmost route name is ValidateLogin. This can be implemented as follows:

    const {tooltipToRender, shouldShowTooltip} = useMemo(() => {

    Update to:

        const rootState = navigationRef.getRootState() as State<RootStackParamList>; // add this line
        const topmostCentralPaneRoute = getTopmostRouteName(rootState); // add this line
    
        const {tooltipToRender, shouldShowTooltip} = useMemo(() => {
            const tooltip = shouldShowGetStartedTooltip ? CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.CONCEIRGE_LHN_GBR : CONST.PRODUCT_TRAINING_TOOLTIP_NAMES.LHN_WORKSPACE_CHAT_TOOLTIP;
            const shouldShowTooltips = shouldShowWokspaceChatTooltip || shouldShowGetStartedTooltip;
            const shouldTooltipBeVisible = shouldUseNarrowLayout ? isScreenFocused && isActiveRouteHome : isActiveRouteHome;
    
            // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
            return {tooltipToRender: tooltip, shouldShowTooltip: shouldShowTooltips && shouldTooltipBeVisible && topmostCentralPaneRoute !== SCREENS.VALIDATE_LOGIN}; // update this line
        }, [shouldShowGetStartedTooltip, shouldShowWokspaceChatTooltip, shouldUseNarrowLayout, isScreenFocused, isActiveRouteHome, topmostCentralPaneRoute]);

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    This is a UI bug, so unit tests are not needed

    What alternative solutions did you explore? (Optional)

    Reminder: Please use plain English, be brief and avoid jargon. Feel free to use images, charts or pseudo-code if necessary. Do not post large multi-line diffs or write walls of text. Do not create PRs unless you have been hired for this job.

  5. linhvovan29546 commented on Jan 12, 2025

    @linhvovan29546
    Contributor

    Edited by proposal-police: This proposal was edited at 2025-01-12 05:17:08 UTC.

    Proposal

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

    Web - Tooltip - Educational tooltip appears on not here page

    What is the root cause of that problem?

    We are displaying the tooltip without verifying if the target element is within the viewable area of the page. This results in the tooltip being shown even when the user cannot see the target content.

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

    We should only display the tooltip if the target element is visible within the viewport (i.e., the user can see the content). To implement this, we can leverage the IntersectionObserver API here to detect the visibility of the target element. Here’s the implementation or we can use similar this library:

    return (
    <GenericTooltip
    shouldForceAnimate
    shouldRender={shouldRender}

    const elementRef = useRef<HTMLElement | null>(null);
    const [intersectionObserverEntry, setIntersectionObserverEntry] = useState<IntersectionObserverEntry>();
        useEffect(() => {
            if (!elementRef.current && !shouldRender) return;
    
            const observer = new IntersectionObserver(
                ([entry]) => {
                    setIntersectionObserverEntry(entry)
                }
            );
            observer.observe(elementRef.current);
            return () => {
                if (elementRef.current) {
                    observer.unobserve(elementRef.current);
                }
            };
        }, [shouldRender]);

    And add ref to here

        <GenericTooltip
                shouldForceAnimate
                shouldRender={shouldRender}
                intersectionObserverEntry={intersectionObserverEntry}
                // eslint-disable-next-line react/jsx-props-no-spreading
                {...props}
            >
                {({ showTooltip, hideTooltip, updateTargetBounds }) => {
                    // eslint-disable-next-line react-compiler/react-compiler
                    hideTooltipRef.current = hideTooltip;
                    return React.cloneElement(children as React.ReactElement, {
                        ref: elementRef,
                        onLayout: (e: LayoutChangeEventWithTarget) => {
                            if (!shouldMeasure) {
                                setShouldMeasure(true);
                            }
                            // e.target is specific to native, use e.nativeEvent.target on web instead
                            const target = e.target || e.nativeEvent.target;
                            show.current = () => measureTooltipCoordinate(target, updateTargetBounds, showTooltip);
                        },
                    });
                }}
            </GenericTooltip>

    And in the BaseGenericTooltip, we need to check the IntersectionObserverEntry to ensure that the content is visible, as shown in the example

    const {rootWrapperStyle, textStyle, pointerWrapperStyle, pointerStyle} = useMemo(
    () =>
    StyleUtils.getTooltipStyles({

        const isElementVisible = useMemo(() => {
            const targetElement = intersectionObserverEntry?.target as HTMLElement;
            let isElementVisible = false
            if (intersectionObserverEntry && intersectionObserverEntry.isIntersecting) {
                const rect = intersectionObserverEntry.intersectionRect
    
                const elementAtPoint = document.elementFromPoint(rect.x + targetWidth / 2, rect.y);
                if (elementAtPoint && 'contains' in targetElement && 'contains' in targetElement) {
                    isElementVisible = targetElement.contains(elementAtPoint) || elementAtPoint.contains(targetElement); //TODO: Add additional conditions to handle cases where the element should be hidden.
    
                }
    
            }
            return isElementVisible
    
        }, [
            anchorAlignment,
            intersectionObserverEntry,
            targetWidth
        ])

    And pass isElementVisible to getTooltipStyles to evaluate the condition.

            if (isTooltipSizeReady && isElementVisible) {
    ...
    }

    I believe this implementation will resolve the root issue where the tooltip is displayed, but the content is not actually visible. For the detailed code, we can discuss it later in PR.

    POC
    Before After
    Screen.Recording.2025-01-12.at.11.15.49.AM.mov
    Screen.Recording.2025-01-12.at.11.15.08.AM.mov

    What specific scenarios should we cover in automated tests to prevent reintroducing this issue in the future?

    No, UI bug

    What alternative solutions did you explore? (Optional)

    We can use my proposal here

  6. removed
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jan 12, 2025
  7. removed their assignment
    on Jan 12, 2025
  8. added
    BugSomething is broken. Auto assigns a BugZero manager.
    on Jan 12, 2025
  9. melvin-bot commented on Jan 12, 2025

    @melvin-bot

    Triggered auto assignment to @twisterdotcom (Bug), see https://stackoverflow.com/c/expensify/questions/14418 for more details. Please add this bug to a GH project, as outlined in the SO.

  10. 27 remaining items

  11. melvin-bot commented on Jan 28, 2025

    @melvin-bot

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

  12. melvin-bot commented on Jan 28, 2025

    @melvin-bot

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

    If no regressions arise, payment will be issued on 2025-02-04. 🎊

    For reference, here are some details about the assignees on this issue:

    • @Ollyws requires payment through NewDot Manual Requests
    • @bernhardoj requires payment through NewDot Manual Requests
  13. melvin-bot commented on Jan 28, 2025

    @melvin-bot

    @Ollyws @twisterdotcom @Ollyws The PR fixing this issue has been merged! The following checklist (instructions) will need to be completed before the issue can be closed. Please copy/paste the BugZero Checklist from here into a new comment on this GH and complete it. If you have the K2 extension, you can simply click: [this button]

  14. melvin-bot commented on Feb 4, 2025

    @melvin-bot

    Payment Summary

    Upwork Job

    BugZero Checklist (@twisterdotcom)

    • I have verified the correct assignees and roles are listed above and updated the neccesary manual offers
    • I have verified that there are no duplicate or incorrect contracts on Upwork for this job (https://www.upwork.com/ab/applicants/1878843621471358356/hired)
    • I have paid out the Upwork contracts or cancelled the ones that are incorrect
    • I have verified the payment summary above is correct
  15. twisterdotcom commented on Feb 4, 2025

    @twisterdotcom
    Contributor

    Bump on the checklist here please @Ollyws.

  16. twisterdotcom commented on Feb 4, 2025

    @twisterdotcom
    Contributor

    Payment Summary:

  17. bernhardoj commented on Feb 5, 2025

    @bernhardoj
    Contributor

    Requested in ND.

  18. Ollyws commented on Feb 5, 2025

    @Ollyws
    Contributor

    BugZero Checklist:

    • [Contributor] Classify the bug:
    Bug classification

    Source of bug:

    • 1a. Result of the original design (eg. a case wasn't considered)
    • 1b. Mistake during implementation
    • 1c. Backend bug
    • 1z. Other:

    Where bug was reported:

    • 2a. Reported on production
    • 2b. Reported on staging (deploy blocker)
    • 2c. Reported on both staging and production
    • 2d. Reported on a PR
    • 2z. Other:

    Who reported the bug:

    • 3a. Expensify user
    • 3b. Expensify employee
    • 3c. Contributor
    • 3d. QA
    • 3z. Other:
    • [Contributor] The offending PR has been commented on, pointing out the bug it caused and why, so the author and reviewers can learn from the mistake.

      Link to comment: 270a302#r152162983

    • [Contributor] If the regression was CRITICAL (e.g. interrupts a core flow) A discussion in #expensify-open-source has been started about whether any other steps should be taken (e.g. updating the PR review checklist) in order to catch this type of bug sooner.

      Link to discussion:

    • [Contributor] If it was decided to create a regression test for the bug, please propose the regression test steps using the template below to ensure the same bug will not reach production again.

    Regression Test Proposal Template
    • [BugZero Assignee] Create a GH issue for creating/updating the regression test once above steps have been agreed upon.

      Link to issue:

    Regression Test Proposal

    Precondition:

    Test:

    1. Login as a new user and complete the onboarding
    2. Create a new workspace
    3. Go back to LHN
    4. Verify there is a tooltip on the workspace chat (if there is other tooltip showing, dismiss it first)
    5. Go to /v/1/1 or a not found page (/asd)
    6. Verify there are no tooltip shows
    7. Go back
    8. Verify the tooltip shows
    

    Do we agree 👍 or 👎

  19. Ollyws commented on Feb 5, 2025

    @Ollyws
    Contributor

    Requested in ND.

  20. JmillsExpensify commented on Feb 10, 2025

    @JmillsExpensify
    Contributor

    $250 approved for @bernhardoj

  21. garrettmknight commented on Feb 11, 2025

    @garrettmknight
    Contributor

    $250 approved for @Ollyws

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

Metadata

Metadata

Labels

Awaiting PaymentAuto-added when associated PR is deployed to productionBugSomething is broken. Auto assigns a BugZero manager.DailyKSv2ExternalAdded to denote the issue can be worked on by a contributor

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions