diff --git a/static/app/components/events/eventTags/eventTagsTreeRow.tsx b/static/app/components/events/eventTags/eventTagsTreeRow.tsx
index 0995f0dea238..b696fd81d653 100644
--- a/static/app/components/events/eventTags/eventTagsTreeRow.tsx
+++ b/static/app/components/events/eventTags/eventTagsTreeRow.tsx
@@ -283,15 +283,7 @@ function EventTagsTreeRowDropdown({
visitExternalLinkAction(content.value),
];
- return (
-
- );
+ return ;
}
function EventTagsTreeValue({
diff --git a/static/app/components/keyValueTree/keyValueTreeRowActions.tsx b/static/app/components/keyValueTree/keyValueTreeRowActions.tsx
index a05d1bbcb506..3c1f73dbe605 100644
--- a/static/app/components/keyValueTree/keyValueTreeRowActions.tsx
+++ b/static/app/components/keyValueTree/keyValueTreeRowActions.tsx
@@ -1,10 +1,12 @@
-import {useState} from 'react';
+import {useContext, useState} from 'react';
+import {useTheme} from '@emotion/react';
import styled from '@emotion/styled';
import {IconEllipsis} from '@sentry/icons/ellipsis';
import {type MenuItemProps} from '@sentry/scraps/dropdownMenu';
import {OverlayTrigger} from '@sentry/scraps/overlayTrigger';
import {RevealOnHover} from '@sentry/scraps/revealOnHover';
+import {TooltipContext} from '@sentry/scraps/tooltip';
import {openNavigateToExternalLinkModal} from 'sentry/actionCreators/modal';
import {t} from 'sentry/locale';
@@ -28,18 +30,22 @@ export function visitExternalLinkAction(value: KeyValueTreeValue): MenuItemProps
export function KeyValueTreeRowActions({
ariaLabel,
items,
- usePortal,
}: {
ariaLabel: string;
items: MenuItemProps[];
- usePortal?: boolean;
}) {
+ const theme = useTheme();
const [isMenuOpen, setIsMenuOpen] = useState(false);
+ const {container} = useContext(TooltipContext);
return (
{
}
// jsdom does not evaluate :hover styles, so bypass the hidden action's pointer-events check.
await userEvent.click(actionsButton, {pointerEventsCheck: 0});
- expect(await within(row).findByText('Visible Action')).toBeInTheDocument();
- expect(await within(row).findByText('Disabled Action')).toBeInTheDocument();
- expect(within(row).queryByText('Hidden Action')).not.toBeInTheDocument();
+ expect(actionsButton).toHaveAttribute('aria-expanded', 'true');
+ expect(within(row).queryByRole('menu')).not.toBeInTheDocument();
+ expect(await screen.findByText('Visible Action')).toBeInTheDocument();
+ expect(await screen.findByText('Disabled Action')).toBeInTheDocument();
+ expect(screen.queryByText('Hidden Action')).not.toBeInTheDocument();
}
});
@@ -418,4 +422,36 @@ describe('attributesTree', () => {
screen.getByTestId('tree-key-sentry.logger.name')
);
});
+
+ it('renders the actions menu in the surrounding overlay container when one is provided', async () => {
+ function OverlayContainer({children}: {children: React.ReactNode}) {
+ const [container, setContainer] = useState(null);
+
+ return (
+
+ {children}
+
+ );
+ }
+
+ render(
+
+
+
+ );
+
+ await userEvent.click(screen.getByRole('button', {name: 'Attribute Actions Menu'}), {
+ pointerEventsCheck: 0,
+ });
+
+ expect(
+ await within(screen.getByTestId('overlay-container')).findByRole('menu')
+ ).toBeInTheDocument();
+ expect(
+ within(screen.getByTestId('attribute-tree-row')).queryByRole('menu')
+ ).not.toBeInTheDocument();
+ });
});
diff --git a/static/packages/scraps/src/dropdownMenu/dropdownMenu.tsx b/static/packages/scraps/src/dropdownMenu/dropdownMenu.tsx
index 3260a9f24af1..9828ddb641fb 100644
--- a/static/packages/scraps/src/dropdownMenu/dropdownMenu.tsx
+++ b/static/packages/scraps/src/dropdownMenu/dropdownMenu.tsx
@@ -63,7 +63,7 @@ interface BaseDropdownMenuProps
/**
* Reference to the container element that the portal should be rendered into.
*/
- portalContainerRef?: React.RefObject;
+ portalContainerRef?: React.RefObject;
/**
* Tag name for the outer wrap, defaults to `div`
*/