Skip to content

Commit 5d320ee

Browse files
authored
Merge pull request #1367 from Gadha2311/keyboard-entrydropdown
feat: enable keyboard support for dropdown selection
2 parents d92d2c3 + 614857e commit 5d320ee

File tree

2 files changed

+79
-32
lines changed

2 files changed

+79
-32
lines changed

src/components/Controls/AutoComplete.vue

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,17 @@
2828
:tabindex="isReadOnly ? '-1' : '0'"
2929
@focus="(e) => !isReadOnly && onInputFocus(e)"
3030
@click="(e) => !isReadOnly && onClick(e, toggleDropdown)"
31-
@blur="(e) => !isReadOnly && onBlur(e.target.value)"
32-
@input="onInput"
33-
@keydown.up="highlightItemUp"
34-
@keydown.down="highlightItemDown"
35-
@keydown.enter="selectHighlightedItem"
36-
@keydown.tab="toggleDropdown(false)"
37-
@keydown.esc="toggleDropdown(false)"
31+
@blur="(e) => !isReadOnly && onBlur(e.target.value, toggleDropdown)"
32+
@input="(e) => onInput(e, toggleDropdown)"
33+
@keydown.up="onKeyDownUp($event, toggleDropdown, highlightItemUp)"
34+
@keydown.down="
35+
onKeyDownDown($event, toggleDropdown, highlightItemDown)
36+
"
37+
@keydown.enter="
38+
onPressEnter($event, toggleDropdown, selectHighlightedItem)
39+
"
40+
@keydown.tab="closeDropdown($event, toggleDropdown)"
41+
@keydown.esc="closeDropdown($event, toggleDropdown)"
3842
/>
3943

4044
<svg
@@ -130,6 +134,7 @@ export default {
130134
suggestions: [],
131135
highlightedIndex: -1,
132136
isFocused: false,
137+
isDropdownOpen: false,
133138
};
134139
},
135140
computed: {
@@ -231,11 +236,10 @@ export default {
231236
getLinkValue(value) {
232237
const oldValue = this.linkValue;
233238
let option = this.options.find((o) => o.value === value);
234-
if (option === undefined) {
239+
if (!option) {
235240
option = this.options.find((o) => o.label === value);
236241
}
237-
238-
if (!value && option === undefined) {
242+
if (!value && !option) {
239243
return null;
240244
}
241245
@@ -254,13 +258,9 @@ export default {
254258
255259
setSetSuggestionAction(suggestions) {
256260
for (const option of suggestions) {
257-
if (option.action) {
258-
continue;
261+
if (!option.action) {
262+
option.action = () => this.setSuggestion(option);
259263
}
260-
261-
option.action = () => {
262-
this.setSuggestion(option);
263-
};
264264
}
265265
266266
return suggestions;
@@ -287,29 +287,28 @@ export default {
287287
this.setLinkValue(suggestion.label);
288288
this.triggerChange(suggestion.value);
289289
}
290-
291-
this.toggleDropdown(false);
292290
},
293291
onInputFocus(e) {
294292
this.isFocused = true;
295293
},
296294
onClick(e, toggleDropdown) {
297295
if (this.isFocused) {
298-
this.toggleDropdown = toggleDropdown;
299-
this.toggleDropdown(true);
296+
toggleDropdown(true);
300297
this.updateSuggestions();
298+
this.isDropdownOpen = true;
301299
this.$emit('focus', e);
302300
}
303301
},
304302
onFocus(e, toggleDropdown) {
305303
this.isFocused = true;
306-
this.toggleDropdown = toggleDropdown;
307-
this.toggleDropdown(true);
304+
toggleDropdown(true);
308305
this.updateSuggestions();
306+
this.isDropdownOpen = true;
309307
this.$emit('focus', e);
310308
},
311-
async onBlur(label) {
309+
async onBlur(label, toggleDropdown) {
312310
this.isFocused = false;
311+
this.isDropdownOpen = false;
313312
if (!label && !this.value) {
314313
return;
315314
}
@@ -331,23 +330,61 @@ export default {
331330
this.setSuggestion(suggestions[0]);
332331
}
333332
},
334-
onInput(e) {
333+
334+
onInput(e, toggleDropdown) {
335335
if (this.isReadOnly) {
336336
return;
337337
}
338338
339339
if (!e.target.value || this.focInp) {
340340
e.target.value = null;
341341
this.focInp = false;
342-
this.toggleDropdown(false);
343-
342+
toggleDropdown(false);
344343
return;
345344
}
346345
347346
this.triggerChange(e.target.value);
348-
this.toggleDropdown(true);
349347
this.updateSuggestions(e.target.value);
350348
},
349+
350+
async onPressEnter(e, toggleDropdown, selectHighlightedItem) {
351+
e.preventDefault();
352+
353+
if (
354+
this.suggestions.length > 0 &&
355+
this.isFocused &&
356+
this.isDropdownOpen
357+
) {
358+
await selectHighlightedItem();
359+
this.closeDropdown(e, toggleDropdown);
360+
return;
361+
}
362+
363+
await this.updateSuggestions(this.linkValue || e.target.value);
364+
toggleDropdown(true);
365+
this.isDropdownOpen = true;
366+
},
367+
368+
onKeyDownUp(e, toggleDropdown, highlightItemUp) {
369+
if (this.suggestions.length === 0) {
370+
this.updateSuggestions();
371+
toggleDropdown(true);
372+
this.isDropdownOpen = true;
373+
}
374+
highlightItemUp();
375+
},
376+
onKeyDownDown(e, toggleDropdown, highlightItemDown) {
377+
if (this.suggestions.length === 0) {
378+
this.updateSuggestions();
379+
toggleDropdown(true);
380+
this.isDropdownOpen = true;
381+
}
382+
highlightItemDown();
383+
},
384+
closeDropdown(e, toggleDropdown) {
385+
toggleDropdown(false);
386+
this.isDropdownOpen = false;
387+
},
351388
},
352389
};
353390
</script>

src/components/Dropdown.vue

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,12 @@ export default defineComponent({
190190
}
191191
192192
if (this.doc) {
193-
return await d.action(this.doc, this.$router);
193+
await d.action(this.doc, this.$router);
194+
} else {
195+
await d.action();
194196
}
195197
196-
await d.action();
198+
this.toggleDropdown(false);
197199
},
198200
toggleDropdown(flag?: boolean): void {
199201
if (typeof flag !== 'boolean') {
@@ -203,9 +205,17 @@ export default defineComponent({
203205
this.isShown = flag;
204206
},
205207
async selectHighlightedItem(): Promise<void> {
206-
let item = this.items[this.highlightedIndex];
207-
if (!item && this.dropdownItems.length === 1) {
208-
item = this.dropdownItems[0];
208+
let item = this.dropdownItems[this.highlightedIndex];
209+
if (!item) {
210+
if (this.dropdownItems.length === 1) {
211+
item = this.dropdownItems[0];
212+
} else {
213+
return;
214+
}
215+
}
216+
217+
if (item.isGroup) {
218+
return;
209219
}
210220
211221
return await this.selectItem(item);

0 commit comments

Comments
 (0)