diff --git a/CHANGELOG.md b/CHANGELOG.md index bbfb6daf648..aae3e0ce6df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Fixed content in `EuiFilterButton` when `numFilters` is not passed ([#5012](https://github.com/elastic/eui/pull/5012)) - Fixed default value of `outsideClickCloses` prop of `EuiFlyout` ([#5027](https://github.com/elastic/eui/pull/5027)) +- Fixed `EuiSelectable`'s double click bug ([#5021](https://github.com/elastic/eui/pull/5021)) ## [`37.2.0`](https://github.com/elastic/eui/tree/v37.2.0) diff --git a/src/components/selectable/__snapshots__/selectable.test.tsx.snap b/src/components/selectable/__snapshots__/selectable.test.tsx.snap index 96a0b54fd75..35ce39017b3 100644 --- a/src/components/selectable/__snapshots__/selectable.test.tsx.snap +++ b/src/components/selectable/__snapshots__/selectable.test.tsx.snap @@ -54,3 +54,43 @@ exports[`EuiSelectable props singleSelection 1`] = ` class="euiSelectable" /> `; + +exports[`EuiSelectable should not reset the activeOptionIndex nor isFocused when EuiSelectable is blurred in favour of its popover 1`] = ` +Object { + "activeOptionIndex": 0, + "isFocused": true, + "searchValue": "", + "visibleOptions": Array [ + Object { + "data-test-subj": "titanOption", + "label": "Titan", + }, + Object { + "label": "Enceladus", + }, + Object { + "label": "Pandora is one of Saturn's moons, named for a Titaness of Greek mythology", + }, + ], +} +`; + +exports[`EuiSelectable should not reset the activeOptionIndex nor isFocused when EuiSelectable is blurred in favour of its popover 2`] = ` +Object { + "activeOptionIndex": 0, + "isFocused": true, + "searchValue": "", + "visibleOptions": Array [ + Object { + "data-test-subj": "titanOption", + "label": "Titan", + }, + Object { + "label": "Enceladus", + }, + Object { + "label": "Pandora is one of Saturn's moons, named for a Titaness of Greek mythology", + }, + ], +} +`; diff --git a/src/components/selectable/selectable.test.tsx b/src/components/selectable/selectable.test.tsx index ef63c131616..3eda2107cb6 100644 --- a/src/components/selectable/selectable.test.tsx +++ b/src/components/selectable/selectable.test.tsx @@ -36,6 +36,31 @@ describe('EuiSelectable', () => { expect(component).toMatchSnapshot(); }); + test('should not reset the activeOptionIndex nor isFocused when EuiSelectable is blurred in favour of its popover', () => { + const component = mount( + + {(list, search) => ( + <> + {list} + {search} + + )} + + ); + + component.setState({ + activeOptionIndex: 0, + isFocused: true, + }); + expect(component.state()).toMatchSnapshot(); + + component.find('.euiSelectable').simulate('blur', { + relatedTarget: { firstChild: { id: 'generated-id_listbox' } }, + }); + component.update(); + expect(component.state()).toMatchSnapshot(); + }); + describe('props', () => { test('searchable', () => { const component = render(); diff --git a/src/components/selectable/selectable.tsx b/src/components/selectable/selectable.tsx index 409522a777d..d33c7e6698e 100644 --- a/src/components/selectable/selectable.tsx +++ b/src/components/selectable/selectable.tsx @@ -330,7 +330,12 @@ export class EuiSelectable extends Component< onContainerBlur = (e: React.FocusEvent) => { // Ignore blur events when moving from search to option to avoid activeOptionIndex conflicts - if (this.containerRef.current!.contains(e.relatedTarget as Node)) return; + if ( + ((e.relatedTarget as Node)?.firstChild as HTMLElement)?.id === + this.rootId('listbox') + ) { + return; + } this.setState({ activeOptionIndex: undefined,