Merge pull request #31406 from fcamgz/search-modal-overflow-fix

Fixed SearchModal not cleaning up body overflow
This commit is contained in:
Patrik Oldsberg
2026-03-28 09:58:09 +01:00
committed by GitHub
3 changed files with 41 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-search': patch
---
Fixed the `SearchModal` leaving the page in a broken state by not restoring body overflow and aria-hidden attributes when closing.
@@ -155,22 +155,6 @@ describe('SearchModal', () => {
expect(toggleModal).toHaveBeenCalledTimes(1);
});
it('should render SearchModal hiding its content', async () => {
const { getByTestId } = await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<SearchModal open hidden toggleModal={toggleModal} />
</ApiProvider>,
{
mountedRoutes: {
'/search': rootRouteRef,
},
},
);
expect(getByTestId('search-bar-next')).toBeInTheDocument();
expect(getByTestId('search-bar-next')).not.toBeVisible();
});
it('should focus on its search bar when opened', async () => {
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
@@ -252,4 +236,36 @@ describe('SearchModal', () => {
expect(navigate).toHaveBeenCalledWith('/search?query=term');
});
it('should completely unmount the Dialog from DOM when open prop is false', async () => {
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<SearchModal open={false} hidden={false} toggleModal={toggleModal} />
</ApiProvider>,
{
mountedRoutes: {
'/search': rootRouteRef,
},
},
);
// Dialog should not exist in the DOM at all (unmounted, not just hidden)
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('should completely unmount the Dialog from DOM when hidden prop is true', async () => {
await renderInTestApp(
<ApiProvider apis={apiRegistry}>
<SearchModal open hidden toggleModal={toggleModal} />
</ApiProvider>,
{
mountedRoutes: {
'/search': rootRouteRef,
},
},
);
// Dialog should not exist in the DOM at all (unmounted, not just hidden)
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
});
@@ -211,6 +211,8 @@ export const SearchModal = (props: SearchModalProps) => {
const classes = useStyles();
const isDialogOpen = open && !hidden;
return (
<Dialog
classes={{
@@ -221,10 +223,9 @@ export const SearchModal = (props: SearchModalProps) => {
aria-modal="true"
fullWidth
maxWidth="lg"
open={open}
hidden={hidden}
open={isDialogOpen}
>
{open && (
{isDialogOpen && (
<SearchContextProvider inheritParentContextIfAvailable>
{(children &&
children({