mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-08-27 12:13:30 +00:00
♿ fix: Keep Portaled Dropdown Menus Clickable Inside Modal Dialogs (#15026)
* fix: keep portaled dropdown menus clickable inside modal dialogs Modal OGDialog layers set pointer-events: none on body and re-enable it only on their own content. A portaled DropdownPopup menu is a body-level sibling of those layers, so it inherited pointer-events: none: hover never reached the items and every click passed through to nothing, which Ariakit treated as an outside interaction and closed the menu. This made the Agent File Search and File Context upload menus dead when SharePoint was enabled, since that flag is what switches them from a plain in-dialog button to the portaled menu. Restore pointer-events: auto on the menu element so it stays clickable regardless of the surrounding modal layers. Fixes #14487 * fix: sort imports in DropdownPopup spec
This commit is contained in:
parent
f1fbaeb6d8
commit
bf3fb17b58
2 changed files with 40 additions and 1 deletions
35
packages/client/src/components/DropdownPopup.spec.tsx
Normal file
35
packages/client/src/components/DropdownPopup.spec.tsx
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
import React from 'react';
|
||||
import * as Ariakit from '@ariakit/react';
|
||||
import { render } from '@testing-library/react';
|
||||
import DropdownPopup from './DropdownPopup';
|
||||
|
||||
describe('DropdownPopup', () => {
|
||||
it('restores pointer events on portaled menus so they stay clickable inside modal dialogs', () => {
|
||||
// A modal Radix dialog (OGDialog) sets `pointer-events: none` on body and only
|
||||
// re-enables it on its own content. A portaled menu is a body-level sibling and
|
||||
// would inherit `none`, making every item hit-transparent (#14487).
|
||||
document.body.style.pointerEvents = 'none';
|
||||
|
||||
render(
|
||||
<DropdownPopup
|
||||
menuId="portal-click-test-menu"
|
||||
isOpen={true}
|
||||
setIsOpen={jest.fn()}
|
||||
modal={true}
|
||||
unmountOnHide={true}
|
||||
trigger={
|
||||
<Ariakit.MenuButton>
|
||||
<span>trigger</span>
|
||||
</Ariakit.MenuButton>
|
||||
}
|
||||
items={[{ label: 'From Local Computer', onClick: jest.fn() }]}
|
||||
/>,
|
||||
);
|
||||
|
||||
const menu = document.getElementById('portal-click-test-menu');
|
||||
expect(menu).not.toBeNull();
|
||||
expect(menu?.style.pointerEvents).toBe('auto');
|
||||
|
||||
document.body.style.pointerEvents = '';
|
||||
});
|
||||
});
|
||||
|
|
@ -89,7 +89,11 @@ const Menu: React.FC<MenuProps> = ({
|
|||
finalFocus={finalFocus}
|
||||
unmountOnHide={unmountOnHide}
|
||||
preserveTabOrder={preserveTabOrder}
|
||||
style={{ zIndex, ...style }}
|
||||
/* Portaled menus land beside modal OGDialog layers, which set
|
||||
`pointer-events: none` on body and re-enable it only on their own
|
||||
content. Without this the menu inherits `none` and its items become
|
||||
hit-transparent (danny-avila/LibreChat#14487). */
|
||||
style={{ zIndex, pointerEvents: 'auto', ...style }}
|
||||
className={cn('popover-ui', className)}
|
||||
{...props}
|
||||
>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue