Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tame-planes-smile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"react-select": patch
---

Fix menu unexpectedly closing when blur on the input is caused by focus moving to a focusable element inside the menu (e.g. a checkbox in a custom `Option` component), even when `closeMenuOnSelect={false}`. The existing guard only checked `document.activeElement`, which does not reliably reflect the newly focused element inside a synchronous blur handler across browsers; the blur event's `relatedTarget` is now also checked.
6 changes: 5 additions & 1 deletion packages/react-select/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1516,7 +1516,11 @@ export default class Select<
};
onInputBlur: FocusEventHandler<HTMLInputElement> = (event) => {
const { inputValue: prevInputValue } = this.props;
if (this.menuListRef && this.menuListRef.contains(document.activeElement)) {
if (
this.menuListRef &&
(this.menuListRef.contains(document.activeElement) ||
this.menuListRef.contains(event.relatedTarget as Node))
) {
this.inputRef!.focus();
return;
}
Expand Down
18 changes: 18 additions & 0 deletions packages/react-select/src/__tests__/Select.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2688,6 +2688,24 @@ test('onMenuClose() function prop to be called on blur', () => {
expect(onMenuCloseSpy).toHaveBeenCalledTimes(1);
});

test('onMenuClose() should not be called when blur is caused by focus moving to an element inside the menu (e.g. a custom Option checkbox)', () => {
let onMenuCloseSpy = jest.fn();
let { container } = render(
<Select
{...BASIC_PROPS}
menuIsOpen
onBlur={jest.fn()}
onInputChange={jest.fn()}
onMenuClose={onMenuCloseSpy}
/>
);
let optionInMenu = container.querySelector('.react-select__option')!;
fireEvent.blur(container.querySelector('input.react-select__input')!, {
relatedTarget: optionInMenu,
});
expect(onMenuCloseSpy).not.toHaveBeenCalled();
});

cases(
'placeholder',
({ props, expectPlaceholder = 'Select...' }) => {
Expand Down