From fd5f7d5a4ae5853d88d48703852f8d82c7171d1f Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Tue, 14 Apr 2026 14:36:59 -0700 Subject: [PATCH 1/3] disable body scoll on modal,tests --- .../src/SelectPanel/SelectPanel.module.css | 2 +- .../src/SelectPanel/SelectPanel.test.tsx | 24 +++++++++++++++++++ .../react/src/SelectPanel/SelectPanel.tsx | 6 ++--- 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/react/src/SelectPanel/SelectPanel.module.css b/packages/react/src/SelectPanel/SelectPanel.module.css index 3a999ad1a60..7fc46e2b1fb 100644 --- a/packages/react/src/SelectPanel/SelectPanel.module.css +++ b/packages/react/src/SelectPanel/SelectPanel.module.css @@ -226,7 +226,7 @@ } .Backdrop { - position: absolute; + position: fixed; inset: 0; background-color: var(--overlay-backdrop-bgColor); } diff --git a/packages/react/src/SelectPanel/SelectPanel.test.tsx b/packages/react/src/SelectPanel/SelectPanel.test.tsx index de52939b1ac..898269e7c06 100644 --- a/packages/react/src/SelectPanel/SelectPanel.test.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.test.tsx @@ -1193,6 +1193,30 @@ for (const usingRemoveActiveDescendant of [false, true]) { expect(screen.getByRole('button', {name: 'Save'})).toBeInTheDocument() expect(screen.getByRole('button', {name: 'Cancel'})).toBeInTheDocument() }) + + it('locks body scroll when modal is open', async () => { + const user = userEvent.setup() + + renderWithProp( {}} />, usingRemoveActiveDescendant) + + expect(document.body.style.overflow).not.toBe('hidden') + + await user.click(screen.getByText('Select items')) + + expect(document.body.style.overflow).toBe('hidden') + }) + + it('restores body scroll when modal is closed', async () => { + const user = userEvent.setup() + + renderWithProp( {}} />, usingRemoveActiveDescendant) + + await user.click(screen.getByText('Select items')) + expect(document.body.style.overflow).toBe('hidden') + + await user.click(screen.getByRole('button', {name: 'Cancel'})) + expect(document.body.style.overflow).not.toBe('hidden') + }) }) describe('sorting', () => { diff --git a/packages/react/src/SelectPanel/SelectPanel.tsx b/packages/react/src/SelectPanel/SelectPanel.tsx index 04667503618..0b8162ca50b 100644 --- a/packages/react/src/SelectPanel/SelectPanel.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.tsx @@ -362,9 +362,9 @@ function Panel({ [items, itemsInViewSet, onSelectedChange, selected], ) - // disable body scroll when the panel is open on narrow screens + // disable body scroll when the panel is open in modal mode or on narrow screens useEffect(() => { - if (open && isNarrowScreenSize && usingFullScreenOnNarrow) { + if (open && (variant === 'modal' || (isNarrowScreenSize && usingFullScreenOnNarrow))) { const bodyOverflowStyle = document.body.style.overflow || '' // If the body is already set to overflow: hidden, it likely means // that there is already a modal open. In that case, we should bail @@ -379,7 +379,7 @@ function Panel({ document.body.style.overflow = bodyOverflowStyle } } - }, [isNarrowScreenSize, open, usingFullScreenOnNarrow]) + }, [isNarrowScreenSize, open, usingFullScreenOnNarrow, variant]) useEffect(() => { if (open) { From dd2d942b5a994dc704f5bc9f8d8262acdccf881d Mon Sep 17 00:00:00 2001 From: Liu Liu Date: Tue, 14 Apr 2026 14:37:42 -0700 Subject: [PATCH 2/3] changeset --- .changeset/gold-humans-tap.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/gold-humans-tap.md diff --git a/.changeset/gold-humans-tap.md b/.changeset/gold-humans-tap.md new file mode 100644 index 00000000000..eafb21a263e --- /dev/null +++ b/.changeset/gold-humans-tap.md @@ -0,0 +1,5 @@ +--- +'@primer/react': patch +--- + +SelectPanel: Lock body scroll when modal variant is on. From f5b44c8caf5615f4c3cbbedf110dd9a848fb6ed2 Mon Sep 17 00:00:00 2001 From: LiuLiu Date: Tue, 14 Apr 2026 16:25:54 -0700 Subject: [PATCH 3/3] add waitfor Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- packages/react/src/SelectPanel/SelectPanel.test.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/packages/react/src/SelectPanel/SelectPanel.test.tsx b/packages/react/src/SelectPanel/SelectPanel.test.tsx index 898269e7c06..743d41aa0b9 100644 --- a/packages/react/src/SelectPanel/SelectPanel.test.tsx +++ b/packages/react/src/SelectPanel/SelectPanel.test.tsx @@ -1203,7 +1203,9 @@ for (const usingRemoveActiveDescendant of [false, true]) { await user.click(screen.getByText('Select items')) - expect(document.body.style.overflow).toBe('hidden') + await waitFor(() => { + expect(document.body.style.overflow).toBe('hidden') + }) }) it('restores body scroll when modal is closed', async () => { @@ -1212,10 +1214,14 @@ for (const usingRemoveActiveDescendant of [false, true]) { renderWithProp( {}} />, usingRemoveActiveDescendant) await user.click(screen.getByText('Select items')) - expect(document.body.style.overflow).toBe('hidden') + await waitFor(() => { + expect(document.body.style.overflow).toBe('hidden') + }) await user.click(screen.getByRole('button', {name: 'Cancel'})) - expect(document.body.style.overflow).not.toBe('hidden') + await waitFor(() => { + expect(document.body.style.overflow).not.toBe('hidden') + }) }) })