Skip to content

Commit 0da42a4

Browse files
committed
feat: add keyboard navigation in the suggestions list
1 parent 99c115a commit 0da42a4

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
@@ -855,7 +855,7 @@ define(function (require, exports, module) {
855855
}
856856

857857
let html = '<ul class="folder-suggestions-list">';
858-
matches.forEach((match) => {
858+
matches.forEach((match, index) => {
859859
let displayHTML = '';
860860
let folderPath = '';
861861

@@ -876,7 +876,9 @@ define(function (require, exports, module) {
876876
folderPath = match.label || '';
877877
}
878878

879-
html += `<li class="folder-suggestion-item" data-path="${folderPath}">${displayHTML}</li>`;
879+
// first item should be selected by default
880+
const selectedClass = index === 0 ? ' selected' : '';
881+
html += `<li class="folder-suggestion-item${selectedClass}" data-path="${folderPath}">${displayHTML}</li>`;
880882
});
881883
html += '</ul>';
882884

@@ -914,6 +916,70 @@ define(function (require, exports, module) {
914916
_renderFolderSuggestions(matches, $suggestions, $input);
915917
}
916918

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

1010+
// input event handler
1011+
$input.on('input', function() {
1012+
_updateFolderSuggestions($input.val(), folderList, stringMatcher, $suggestions, $input);
1013+
});
1014+
_registerFolderDialogInputHandlers($input, $suggestions, $dlg);
9491015
// focus the input box
9501016
setTimeout(function() {
9511017
$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)