DropdownMenu / Filters and ContextMenu positioning issues inside scrollable containers

Hi Handsontable Team,

We found two positioning issues with DropdownMenu, Filters, and ContextMenu when Handsontable is placed inside a scrollable container.

Environment

  • Handsontable React

  • Vite

  • Latest Handsontable version

  • Reproduced in a clean StackBlitz project

  • No PrimeReact, Tailwind, or application-specific code required

Reproduction

StackBlitz:

https://stackblitz.com/edit/vitejs-vite-5scefubs?file=index.html,src%2FApp.tsx

The sample contains:

  • Fixed Header

  • Scrollable Content Area (overflow:auto)

  • Handsontable

  • Fixed Footer

  • dropdownMenu: true

  • filters: true

  • contextMenu: true


Issue 1: DropdownMenu / Filters popup does not move with table while scrolling

Steps

  1. Open a column filter menu.

  2. Keep the menu open.

  3. Scroll the parent container.

Expected

The filter menu should remain attached to the column header and move together with the table.

Actual

The filter menu remains at its original screen position while the table scrolls underneath it.

From DevTools we can see that the menu is rendered inside:

<div class="ht-portal">
  <div class="htDropdownMenu">

and the menu position is calculated once using top/left coordinates.

The coordinates are not recalculated when the parent scroll container moves.


Issue 2: DropdownMenu / ContextMenu overlays fixed header and footer

Steps

  1. Open DropdownMenu or ContextMenu.

  2. Scroll the content area.

Expected

The popup should remain visually associated with the table and avoid overlapping application-level fixed header/footer regions.

Actual

DropdownMenu and ContextMenu can overlap fixed headers and footers because they are rendered in the global portal layer and are not constrained to the scroll container.

@kranthikumar.reddy32 thank you for the detailed report and StackBlitz example. I’ve created an issue in GitHub:

I’ll update this thread once the issue is fixed.

In the meantime, there’s a supported workaround: the uiContainer setting. It tells the ContextMenu and DropdownMenu/Filters to render their elements inside an element you choose instead of the global portal. If you point it at your scrollable content area, the menus become children of that container, so they scroll together with the table and can no longer paint over your fixed header and footer.

A few notes:

Passing dropdownMenu={{ uiContainer: … }} without items keeps the default menu items (including the filter UI), so you don’t need to redefine anything. The Filters dropdown automatically uses the DropdownMenu’s uiContainer.

Make sure the container element exists before Handsontable initializes (in React, render the grid after the ref is set, or pass the element once mounted).

The trade-off: menus are now clipped by the container’s bounds, so a menu opened near the bottom edge may be cut off or extend the container’s scroll area instead of overflowing it. That’s the reason menus render in a global portal by default.

We’ll follow up here once the underlying fix (making menus react to ancestor container scroll) ships.

Hi @kranthikumar.reddy32 , this issue has been fixed with the v18 release. Please let me know if you still have any issues after updating.