Skip to content

Commit 036d0be

Browse files
vaadin-botjouni
andauthored
fix: keep combo-box overlay visible during closing animation (#12115) (#12122)
Co-authored-by: Jouni Koivuviita <jouni@vaadin.com>
1 parent 8e5b36b commit 036d0be

5 files changed

Lines changed: 99 additions & 5 deletions

File tree

packages/combo-box/src/vaadin-combo-box-base-mixin.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,12 @@ export const ComboBoxBaseMixin = (superClass) =>
220220
this._overlayOpened = e.detail.value;
221221
});
222222

223+
// Finish close lifecycle only after the overlay closing animation completes.
224+
overlay.addEventListener('vaadin-overlay-closed', () => {
225+
this._scroller.items = [];
226+
this._onOverlayClosed();
227+
});
228+
223229
this._overlayElement = overlay;
224230
}
225231

@@ -266,7 +272,6 @@ export const ComboBoxBaseMixin = (superClass) =>
266272
this._onOpened();
267273
} else if (wasOpened && this._hasDropdownItems) {
268274
this.close();
269-
this._onOverlayClosed();
270275
}
271276
}
272277

@@ -716,6 +721,10 @@ export const ComboBoxBaseMixin = (superClass) =>
716721
// Stop this private event from leaking outside.
717722
e.stopPropagation();
718723

724+
if (this.hasAttribute('closing')) {
725+
return;
726+
}
727+
719728
if (e.detail.item instanceof ComboBoxPlaceholder) {
720729
// Placeholder items should not be selectable.
721730
return;

packages/combo-box/src/vaadin-combo-box-mixin.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,10 @@ export const ComboBoxMixin = (superClass) =>
165165
getComputedStyle(this).getPropertyValue(`--${this._tagNamePrefix}-overlay-max-height`) || '65vh';
166166
}
167167

168+
const isClosing = this.hasAttribute('closing');
169+
168170
this._scroller.setProperties({
169-
items: opened ? items : [],
171+
items: opened || isClosing ? items : [],
170172
opened,
171173
focusedIndex,
172174
theme,

packages/combo-box/test/interactions.test.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
focusout,
1010
nextRender,
1111
nextUpdate,
12+
oneEvent,
1213
outsideClick,
1314
tabKeyDown,
1415
tap,
@@ -106,6 +107,44 @@ describe('interactions', () => {
106107
focusout(input);
107108
expect(input.value).to.be.empty;
108109
});
110+
111+
it('should not select item when clicked during closing animation', async () => {
112+
const style = document.createElement('style');
113+
style.textContent = `
114+
:host([closing]) {
115+
animation: 200ms closing-animation;
116+
}
117+
118+
:host([closing]) [part='overlay'] {
119+
animation: 200ms overlay-closing-animation;
120+
}
121+
122+
@keyframes closing-animation {
123+
to {
124+
opacity: 1;
125+
}
126+
}
127+
128+
@keyframes overlay-closing-animation {
129+
to {
130+
opacity: 0;
131+
}
132+
}
133+
`;
134+
overlay.shadowRoot.appendChild(style);
135+
136+
const item = getFirstItem(comboBox);
137+
comboBox.close();
138+
await sendMouseToElement({ type: 'click', element: item });
139+
140+
expect(comboBox.selectedItem).to.be.null;
141+
expect(comboBox.value).to.be.empty;
142+
143+
await oneEvent(overlay, 'vaadin-overlay-closed');
144+
145+
expect(comboBox.selectedItem).to.be.null;
146+
expect(comboBox.value).to.be.empty;
147+
});
109148
});
110149

111150
describe('focus', () => {

packages/multi-select-combo-box/src/vaadin-multi-select-combo-box-mixin.js

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,10 @@ export const MultiSelectComboBoxMixin = (superClass) =>
471471
getComputedStyle(this).getPropertyValue(`--${this._tagNamePrefix}-overlay-max-height`) || '65vh';
472472
}
473473

474+
const isClosing = this.hasAttribute('closing');
475+
474476
this._scroller.setProperties({
475-
items: opened ? items : [],
477+
items: opened || isClosing ? items : [],
476478
opened,
477479
focusedIndex,
478480
theme,
@@ -1270,6 +1272,10 @@ export const MultiSelectComboBoxMixin = (superClass) =>
12701272
_overlaySelectedItemChanged(event) {
12711273
event.stopPropagation();
12721274

1275+
if (this.hasAttribute('closing')) {
1276+
return;
1277+
}
1278+
12731279
// Do not un-select on click when readonly
12741280
if (this.readonly) {
12751281
return;

packages/multi-select-combo-box/test/selecting-items.test.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { expect } from '@vaadin/chai-plugins';
2-
import { resetMouse, sendKeys, sendMouse } from '@vaadin/test-runner-commands';
3-
import { fixtureSync, keyboardEventFor, nextRender } from '@vaadin/testing-helpers';
2+
import { resetMouse, sendKeys, sendMouse, sendMouseToElement } from '@vaadin/test-runner-commands';
3+
import { fixtureSync, keyboardEventFor, nextRender, oneEvent } from '@vaadin/testing-helpers';
44
import sinon from 'sinon';
55
import '../src/vaadin-multi-select-combo-box.js';
66
import { getAllItems, getDataProvider, getFirstItem } from './helpers.js';
@@ -203,6 +203,44 @@ describe('selecting items', () => {
203203
expect(comboBox.filter).to.equal('an');
204204
expect(inputElement.value).to.equal('an');
205205
});
206+
207+
it('should not select item when clicked during closing animation', async () => {
208+
const overlay = comboBox.$.overlay;
209+
const style = document.createElement('style');
210+
style.textContent = `
211+
:host([closing]) {
212+
animation: 200ms closing-animation;
213+
}
214+
215+
:host([closing]) [part='overlay'] {
216+
animation: 200ms overlay-closing-animation;
217+
}
218+
219+
@keyframes closing-animation {
220+
to {
221+
opacity: 1;
222+
}
223+
}
224+
225+
@keyframes overlay-closing-animation {
226+
to {
227+
opacity: 0;
228+
}
229+
}
230+
`;
231+
overlay.shadowRoot.appendChild(style);
232+
233+
await sendKeys({ down: 'ArrowDown' });
234+
const item = getFirstItem(comboBox);
235+
comboBox.close();
236+
await sendMouseToElement({ type: 'click', element: item });
237+
238+
expect(comboBox.selectedItems).to.deep.equal([]);
239+
240+
await oneEvent(overlay, 'vaadin-overlay-closed');
241+
242+
expect(comboBox.selectedItems).to.deep.equal([]);
243+
});
206244
});
207245

208246
describe('dataProvider', () => {

0 commit comments

Comments
 (0)