From 600d51bb8fa387d702a7347beeb09edc60f99de2 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Apr 2026 10:38:55 +0200 Subject: [PATCH 1/3] ref(compactSelect): Auto-select single option on Enter when searching When a user searches and narrows the list down to exactly one visible option, pressing Enter now selects that option automatically instead of doing nothing. If multiple options are still visible, Enter continues to have no effect (preventing accidental selections). Co-Authored-By: Claude --- .../core/compactSelect/compactSelect.spec.tsx | 54 +++++++++++++++++++ .../components/core/compactSelect/control.tsx | 11 +++- 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/static/app/components/core/compactSelect/compactSelect.spec.tsx b/static/app/components/core/compactSelect/compactSelect.spec.tsx index 995a13dd51e6be..b60ba8d8bfed52 100644 --- a/static/app/components/core/compactSelect/compactSelect.spec.tsx +++ b/static/app/components/core/compactSelect/compactSelect.spec.tsx @@ -447,6 +447,60 @@ describe('CompactSelect', () => { expect(screen.queryByRole('option', {name: 'Option One'})).not.toBeInTheDocument(); }); + it('selects the single remaining option when Enter is pressed', async () => { + const onChange = jest.fn(); + render( + + ); + + await userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByPlaceholderText('Search here…')); + + // type 'Two' to narrow the list to exactly one option + await userEvent.keyboard('Two'); + expect(screen.getByRole('option', {name: 'Option Two'})).toBeInTheDocument(); + expect(screen.queryByRole('option', {name: 'Option One'})).not.toBeInTheDocument(); + + // pressing Enter should select the single visible option + await userEvent.keyboard('{Enter}'); + expect(onChange).toHaveBeenCalledWith(expect.objectContaining({value: 'opt_two'})); + }); + + it('does not auto-select when multiple options are visible and Enter is pressed', async () => { + const onChange = jest.fn(); + render( + + ); + + await userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByPlaceholderText('Search here…')); + + // type 'Option' — both options are still visible + await userEvent.keyboard('Option'); + expect(screen.getByRole('option', {name: 'Option One'})).toBeInTheDocument(); + expect(screen.getByRole('option', {name: 'Option Two'})).toBeInTheDocument(); + + // pressing Enter should not select anything + await userEvent.keyboard('{Enter}'); + expect(onChange).not.toHaveBeenCalled(); + }); + it('restores full list when search query is cleared', async () => { render( (`li[role="${role}"]`) ?? + []), + ].filter(opt => opt.getAttribute('aria-disabled') !== 'true'); + if (enabledOptions.length === 1) { + enabledOptions[0]?.click(); + } } // Continue propagation, otherwise the overlay won't close on Esc key press From 46fdd2083381ea8b0063425b12ea6be273700473 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Apr 2026 19:13:41 +0200 Subject: [PATCH 2/3] fix(compactSelect): Count all visible options before auto-selecting on Enter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous logic filtered to enabled-only options and checked if exactly one remained. This caused a false positive: when a search matched two visible options where one was disabled, enabledOptions.length was 1 and Enter would auto-select — even though the user could see two items in the list. Fix by counting all visible options first. Auto-select only fires when there is exactly one visible option total and that option is not disabled. Add a regression test covering the one-enabled / one-disabled case. Co-Authored-By: Claude Sonnet 4 --- .../core/compactSelect/compactSelect.spec.tsx | 27 +++++++++++++++++++ .../components/core/compactSelect/control.tsx | 16 +++++++---- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/static/app/components/core/compactSelect/compactSelect.spec.tsx b/static/app/components/core/compactSelect/compactSelect.spec.tsx index b60ba8d8bfed52..b9436a8416b9d4 100644 --- a/static/app/components/core/compactSelect/compactSelect.spec.tsx +++ b/static/app/components/core/compactSelect/compactSelect.spec.tsx @@ -501,6 +501,33 @@ describe('CompactSelect', () => { expect(onChange).not.toHaveBeenCalled(); }); + it('does not auto-select when one enabled and one disabled option are visible', async () => { + const onChange = jest.fn(); + render( + + ); + + await userEvent.click(screen.getByRole('button')); + await userEvent.click(screen.getByPlaceholderText('Search here…')); + + // type 'Option' — both options are visible (one enabled, one disabled) + await userEvent.keyboard('Option'); + expect(screen.getByRole('option', {name: 'Option One'})).toBeInTheDocument(); + expect(screen.getByRole('option', {name: 'Option Two'})).toBeInTheDocument(); + + // pressing Enter must not auto-select even though only one option is enabled + await userEvent.keyboard('{Enter}'); + expect(onChange).not.toHaveBeenCalled(); + }); + it('restores full list when search query is cleared', async () => { render( (`li[role="${role}"]`) ?? []), - ].filter(opt => opt.getAttribute('aria-disabled') !== 'true'); - if (enabledOptions.length === 1) { - enabledOptions[0]?.click(); + ]; + if ( + allVisibleOptions.length === 1 && + allVisibleOptions[0]?.getAttribute('aria-disabled') !== 'true' + ) { + allVisibleOptions[0].click(); } } From 94f8167b5d70af8d6116d733dfbeb67adf170bd8 Mon Sep 17 00:00:00 2001 From: JonasBa Date: Fri, 10 Apr 2026 19:39:55 +0200 Subject: [PATCH 3/3] fix(compactSelect): Use explicit null check instead of non-null assertion Assign the first visible option to a const and guard with a truthiness check before calling click(), making the code runtime safe rather than relying on a non-null assertion operator. Co-Authored-By: Claude --- static/app/components/core/compactSelect/control.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/static/app/components/core/compactSelect/control.tsx b/static/app/components/core/compactSelect/control.tsx index 30e8d1013b7169..974beb98aa65de 100644 --- a/static/app/components/core/compactSelect/control.tsx +++ b/static/app/components/core/compactSelect/control.tsx @@ -284,11 +284,13 @@ export function Control({ ...(overlayRef.current?.querySelectorAll(`li[role="${role}"]`) ?? []), ]; + const firstOption = allVisibleOptions[0]; if ( allVisibleOptions.length === 1 && - allVisibleOptions[0]?.getAttribute('aria-disabled') !== 'true' + firstOption && + firstOption.getAttribute('aria-disabled') !== 'true' ) { - allVisibleOptions[0].click(); + firstOption.click(); } }