Skip to content

fix(overflow-menu): portal-mode menu stretches across viewport, intercepts its own item clicks #1484

@steilerDev

Description

@steilerDev

Summary

After #1481 fixed the close-on-scroll issue, a second bug in OverflowMenu portal mode surfaced: the menu DOM element stretches to fill (or exceed) the entire viewport. Its own bounding box covers the menu item button, intercepting pointer events meant for the item.

Reproduction

Same E2E spec as #1480: e2e/tests/invoices/invoice-deposits.spec.ts:665 (mobile, "Mark paid" flow). Playwright call log after #1481 lands:

```

  1. attempting click action
    • element is visible, enabled and stable
    • intercepts pointer events
  2. retrying click action
    • Jul 20, 2026
      intercepts pointer events
  3. retrying click action
    • intercepts pointer events

```

The all-white failure screenshot from the second attempt visually confirms a viewport-covering element.

Root cause

OverflowMenu.tsx applies BOTH the inline portal positioning AND the .menuTop CSS class regardless of mode:

```jsx
className={`${styles.menu} ${usePortal ? styles.menuFixed : ''} ${placement === 'top-end' ? styles.menuTop : styles.menuBottom}`}
```

`.menuTop` is designed for non-portal (absolute) positioning:

```css
.menuTop {
bottom: 100%;
right: 0;
margin-bottom: var(--spacing-1);
}
```

In portal mode the inline style sets `position: fixed; top: ; right: ; transform: translateY(-100%)`. CSS `.menuTop` adds `bottom: 100%` on top of that. Because both `top` and `bottom` are set on a fixed-positioned element, the menu's height stretches to fill the viewport.

Proposed fix

Apply the `.menuTop`/`.menuBottom` classes only in non-portal mode. In portal mode, positioning is fully controlled by inline styles:

```jsx
className={`${styles.menu} ${usePortal ? styles.menuFixed : ''} ${!usePortal ? (placement === 'top-end' ? styles.menuTop : styles.menuBottom) : ''}`}
```

Acceptance criteria

  • Menu element in portal mode has `auto` height (sized by its content), not stretched to the viewport.
  • `e2e/tests/invoices/invoice-deposits.spec.ts:665` passes on the mobile project in CI.
  • No regression in non-portal mode (existing menus that don't use the portal continue to work).
  • Unit test asserts the menu element does NOT carry `.menuTop` / `.menuBottom` classes when `usePortal=true`.

Scope

  • `client/src/components/OverflowMenu/OverflowMenu.tsx` (one-line className change)
  • `client/src/components/OverflowMenu/OverflowMenu.test.tsx` (add portal-mode class-assertion test)

Blocks

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions