Skip to content

Commit 9c39eea

Browse files
committed
feat: add keyboard navigation in the suggestions list
1 parent 71c3fcd commit 9c39eea

File tree

2 files changed

+74
-8
lines changed

2 files changed

+74
-8
lines changed

src/LiveDevelopment/LivePreviewEdit.js

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ define(function (require, exports, module) {
840840
}
841841

842842
let html = '<ul class="folder-suggestions-list">';
843-
matches.forEach((match) => {
843+
matches.forEach((match, index) => {
844844
let displayHTML = '';
845845
let folderPath = '';
846846

@@ -861,7 +861,9 @@ define(function (require, exports, module) {
861861
folderPath = match.label || '';
862862
}
863863

864-
html += `<li class="folder-suggestion-item" data-path="${folderPath}">${displayHTML}</li>`;
864+
// first item should be selected by default
865+
const selectedClass = index === 0 ? ' selected' : '';
866+
html += `<li class="folder-suggestion-item${selectedClass}" data-path="${folderPath}">${displayHTML}</li>`;
865867
});
866868
html += '</ul>';
867869

@@ -899,6 +901,70 @@ define(function (require, exports, module) {
899901
_renderFolderSuggestions(matches, $suggestions, $input);
900902
}
901903

904+
/**
905+
* register the input box handlers (folder selection dialog)
906+
* also registers the 'arrow up/down and enter' key handler for folder selection and move the selected folder,
907+
* in the list of suggestions
908+
*
909+
* @param {JQuery} $input - the input box element
910+
* @param {JQuery} $suggestions - the suggestions list element
911+
* @param {JQuery} $dlg - the dialog box element
912+
*/
913+
function _registerFolderDialogInputHandlers($input, $suggestions, $dlg) {
914+
// keyboard navigation handler for arrow keys
915+
$input.on('keydown', function(e) {
916+
const $items = $suggestions.find('.folder-suggestion-item');
917+
const $selected = $items.filter('.selected');
918+
919+
if (e.keyCode === 40) { // arrow down key
920+
e.preventDefault();
921+
if ($items.length === 0) { return; }
922+
923+
if ($selected.length === 0) {
924+
$items.first().addClass('selected');
925+
} else {
926+
const currentIndex = $items.index($selected);
927+
$selected.removeClass('selected');
928+
const nextIndex = (currentIndex + 1) % $items.length;
929+
$items.eq(nextIndex).addClass('selected');
930+
}
931+
} else if (e.keyCode === 38) { // arrow up key
932+
e.preventDefault();
933+
if ($items.length === 0) { return; }
934+
935+
if ($selected.length === 0) {
936+
$items.last().addClass('selected');
937+
} else {
938+
const currentIndex = $items.index($selected);
939+
$selected.removeClass('selected');
940+
const nextIndex = (currentIndex - 1 + $items.length) % $items.length;
941+
$items.eq(nextIndex).addClass('selected');
942+
}
943+
}
944+
});
945+
946+
// for enter key, we're using keyup handler because keydown was interfering with dialog's default behaviour
947+
// when enter key is pressed, we check if there are any selected folders in the suggestions
948+
// if yes, we type the folder path in the input box,
949+
// if no, we click the ok button of the dialog
950+
$input.on('keyup', function(e) {
951+
if (e.keyCode === 13) { // enter key
952+
const $items = $suggestions.find('.folder-suggestion-item');
953+
const $selected = $items.filter('.selected');
954+
955+
// if there's a selected suggestion, use it
956+
if ($selected.length > 0) {
957+
const folderPath = $selected.data('path');
958+
$input.val(folderPath);
959+
$suggestions.empty();
960+
} else {
961+
// no suggestions, trigger OK button click
962+
$dlg.find('[data-button-id="ok"]').click();
963+
}
964+
}
965+
});
966+
}
967+
902968
/**
903969
* This function is called when 'use this image' button is clicked in the image ribbon gallery
904970
* or user loads an image file from the computer
@@ -924,13 +990,13 @@ define(function (require, exports, module) {
924990
// Scan project directories and setup event handlers
925991
_scanDirectories(projectRoot, '', folderList).then(() => {
926992
stringMatcher = new StringMatch.StringMatcher({ segmentedSearch: true });
927-
928-
// input event handler
929-
$input.on('input', function() {
930-
_updateFolderSuggestions($input.val(), folderList, stringMatcher, $suggestions, $input);
931-
});
932993
});
933994

995+
// input event handler
996+
$input.on('input', function() {
997+
_updateFolderSuggestions($input.val(), folderList, stringMatcher, $suggestions, $input);
998+
});
999+
_registerFolderDialogInputHandlers($input, $suggestions, $dlg);
9341000
// focus the input box
9351001
setTimeout(function() {
9361002
$input.focus();

src/styles/brackets_patterns_override.less

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2572,7 +2572,7 @@ code {
25722572
}
25732573
}
25742574

2575-
&.highlight {
2575+
&.selected {
25762576
background-color: @bc-bg-highlight;
25772577
border-left-color: @bc-primary-btn-bg;
25782578

0 commit comments

Comments
 (0)