Skip to content

Web - Expense - + menu appears in the middle #77587

Closed

Description

@lanitochka17

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.2.78-0
Reproducible in staging?: Yes
Reproducible in production?: No
If this was caught during regression testing, add the test name, ID and link from BrowserStack: #75886
Email or phone of affected tester (no customers): dsjndijsojnsoijdsio@gmail.com
Issue reported by: Applause Internal Team
Bug source: Pull Request QA execution
Device used: Mac 26.1 / Chrome
App Component: Money Requests

Action Performed:

  1. Go to staging.new.expensify.com
  2. Go to workspace chat.
  3. Create two expenses.
  4. Open expense report.
  5. Open any expense.
  6. Click +.

Expected Result:

  • menu will appear above + button.

Actual Result:

  • menu appears in the middle.

Workaround:

Unknown

Platforms:

  • Android: App
  • Android: mWeb Chrome
  • iOS: App
  • iOS: mWeb Safari
  • iOS: mWeb Chrome
  • Windows: Chrome
  • MacOS: Chrome / Safari

Screenshots/Videos

Bug7028277_1765577941778.4.mp4

View all open jobs on GitHub

Activity

  1. added
    DeployBlockerCashThis issue or pull request should block deployment
    BugSomething is broken. Auto assigns a BugZero manager.
    on Dec 12, 2025
  2. melvin-bot commented on Dec 12, 2025

    @melvin-bot

    Triggered auto assignment to @heyjennahay (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. melvin-bot commented on Dec 12, 2025

    @melvin-bot

    Triggered auto assignment to @iwiznia (DeployBlockerCash), see https://stackoverflowteams.com/c/expensify/questions/9980/ for more details.

  4. melvin-bot commented on Dec 12, 2025

    @melvin-bot

    💬 A slack conversation has been started in #expensify-open-source

  5. github-actions commented on Dec 12, 2025

    @github-actions
    Contributor

    👋 Friendly reminder that deploy blockers are time-sensitive ⏱ issues! Check out the open `StagingDeployCash` deploy checklist to see the list of PRs included in this release, then work quickly to do one of the following:

    1. Identify the pull request that introduced this issue and revert it.
    2. Find someone who can quickly fix the issue.
    3. Fix the issue yourself.
  6. mavrickdeveloper commented on Dec 15, 2025

    @mavrickdeveloper
    Contributor

    Proposal

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

    When viewing an expense in Wide RHP (Right Hand Panel) mode via Search, clicking the + button in the composer area causes the popover menu to appear in the middle of the screen (over the receipt area) instead of appearing above the + button in the chat pane.

    Reproduction Steps:

    1. Navigate to Search > Expenses
    2. Click on any expense to open it in Wide RHP view
    3. Click the + button in the composer at the bottom of the expense detail panel
    4. Expected: Menu appears above the + button in the chat pane
    5. Actual (Bug): Menu appeared in the middle of the screen over the receipt area

    What is the root cause of that problem?

    The root cause is an incorrect geometric calculation in the menu positioning functions for Wide/Super Wide RHP modes.

    In Wide RHP mode, the layout structure is in a way that the chat pane (containing the + button) is always 375px wide and positioned at the right edge of the screen. Therefore, the left edge of the chat pane is at windowWidth - sideBarWidth.

    The buggy code in src/styles/index.ts was calculating the horizontal position incorrectly:

    App/src/styles/index.ts

    Lines 5674 to 5680 in d98ba84

    createMenuPositionReportActionCompose: (shouldUseNarrowLayout: boolean, windowHeight: number, windowWidth: number) =>
    ({
    // On a narrow layout the menu is displayed in ReportScreen in RHP, so it must be moved from the right side of the screen
    horizontal: (shouldUseNarrowLayout ? windowWidth - variables.sideBarWithLHBWidth : variables.sideBarWithLHBWidth + variables.navigationTabBarSize) + variables.popoverMargin,
    vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM,
    }) satisfies AnchorPosition,

    For a 1536px screen, the buggy calculation produced: 320 + 72 + 18 = 410px (left side of screen - WRONG)

    But the + button is actually at: 1536 - 375 + 18 = 1179px (left edge of chat pane - CORRECT)

    While exploring this i identified that in addition to that , the code had two duplicate functions (createMenuPositionWideRHPReportActionCompose and createMenuPositionSuperWideRHPReportActionCompose) with the same buggy logic, and the shouldUseNarrowLayout parameter was never meaningfully used.


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

    1. Consolidate duplicate functions and fix the calculation

    Replace the two buggy duplicate functions with a single correctly-implemented function: At: src/styles/index.ts

    Before (problematic):

    createMenuPositionWideRHPReportActionCompose: (shouldUseNarrowLayout: boolean, windowHeight: number, windowWidth: number) =>
        ({
            horizontal:
                (shouldUseNarrowLayout
                    ? windowWidth - calculateReceiptPaneRHPWidth(windowWidth) - variables.sideBarWidth
                    : variables.sideBarWithLHBWidth + variables.navigationTabBarSize) + variables.popoverMargin,
            vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM,
        }) satisfies AnchorPosition,
    
    createMenuPositionSuperWideRHPReportActionCompose: (shouldUseNarrowLayout: boolean, windowHeight: number, windowWidth: number) =>
        ({
            horizontal:
                (shouldUseNarrowLayout ? windowWidth - calculateSuperWideRHPWidth(windowWidth) : variables.sideBarWithLHBWidth + variables.navigationTabBarSize) +
                variables.popoverMargin,
            vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM,
        }) satisfies AnchorPosition,

    After (fixed):

    /**
     * Returns the anchor position for the popover menu in Wide/Super Wide RHP mode.
     *
     * In both Wide RHP and Super Wide RHP modes, the chat pane (containing the + button)
     * maintains a fixed width of sideBarWidth (375px) and is always positioned at the
     * right edge of the screen. The receipt/transaction pane expands to the left, but
     * the chat pane's position relative to the screen edge remains constant.
     *
     *
     * @param windowHeight - Current window height
     * @param windowWidth - Current window width
     * @returns AnchorPosition for the popover menu
     */
    createMenuPositionExpandedRHPReportActionCompose: (windowHeight: number, windowWidth: number) =>
        ({
            horizontal: windowWidth - variables.sideBarWidth + variables.popoverMargin,
            vertical: windowHeight - CONST.MENU_POSITION_REPORT_ACTION_COMPOSE_BOTTOM,
        }) satisfies AnchorPosition,

    2. Update the consumer to use the consolidated function

    Before:

    const anchorPosition = useMemo(() => {
    if (isSuperWideRHPFocused) {
    return styles.createMenuPositionSuperWideRHPReportActionCompose(shouldUseNarrowLayout, windowHeight, windowWidth);
    }
    if (isWideRHPFocused) {
    return styles.createMenuPositionWideRHPReportActionCompose(shouldUseNarrowLayout, windowHeight, windowWidth);
    }
    return styles.createMenuPositionReportActionCompose(shouldUseNarrowLayout, windowHeight, windowWidth);
    }, [isSuperWideRHPFocused, isWideRHPFocused, styles, shouldUseNarrowLayout, windowHeight, windowWidth]);

    After:

    const anchorPosition = useMemo(() => {
        // Wide RHP and Super Wide RHP share the same positioning logic since
        // the chat pane is always at the right edge with fixed width (sideBarWidth)
        if (isSuperWideRHPFocused || isWideRHPFocused) {
            return styles.createMenuPositionExpandedRHPReportActionCompose(windowHeight, windowWidth);
        }
    
        return styles.createMenuPositionReportActionCompose(shouldUseNarrowLayout, windowHeight, windowWidth);
    }, [isSuperWideRHPFocused, isWideRHPFocused, styles, shouldUseNarrowLayout, windowHeight, windowWidth]);

    Logic behind the above fix

    1. Correct geometric calculation: windowWidth - sideBarWidth + popoverMargin correctly positions the menu at the left edge of the chat pane where the + button is located

    2. No duplicate code: Consolidated two identical buggy functions into one correct function

    3. Removed dead code: The shouldUseNarrowLayout parameter was never meaningfully used in Wide RHP mode and has been removed

    4. No regression: The regular (non-Wide RHP) positioning function createMenuPositionReportActionCompose remains the same


    What alternative solutions did you explore? (Optional)

    --

  7. mavrickdeveloper commented on Dec 15, 2025

    @mavrickdeveloper
    Contributor

    Demonstration for #77587 (comment)

    2025-12-15.07-07-58.mp4
  8. m-natarajan commented on Dec 15, 2025

    @m-natarajan

    Not reproducible on Windows 10/Chrome v9.2.78-1

    bandicam.2025-12-15.15-53-23-652.mp4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.EngineeringHourlyKSv2ReviewingHas a PR in review

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions