62 lines
1.7 KiB
JavaScript
62 lines
1.7 KiB
JavaScript
|
|
/**
|
||
|
|
* Keyboard shortcuts for item search.
|
||
|
|
*
|
||
|
|
* - Up/Down arrows move focus between the search field and the item list,
|
||
|
|
* so keyboard users can quickly browse results without tabbing.
|
||
|
|
* - Escape exits search mode (clicks the back button).
|
||
|
|
*/
|
||
|
|
document.addEventListener("keydown", (e) => {
|
||
|
|
if (e.key === "Escape") {
|
||
|
|
const backButton = document.querySelector(
|
||
|
|
".item-search-form .back-button",
|
||
|
|
);
|
||
|
|
if (!backButton) return;
|
||
|
|
|
||
|
|
// Only act when focus is on the search input or a search result.
|
||
|
|
const section = document.querySelector(".outfit-controls-section");
|
||
|
|
const searchInput = section?.querySelector(
|
||
|
|
'.search-form input[type="text"]',
|
||
|
|
);
|
||
|
|
const isSearchFocused =
|
||
|
|
document.activeElement === searchInput ||
|
||
|
|
document.activeElement?.closest(".search-results-list") != null;
|
||
|
|
if (!isSearchFocused) return;
|
||
|
|
|
||
|
|
e.preventDefault();
|
||
|
|
backButton.click();
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
if (e.key !== "ArrowDown" && e.key !== "ArrowUp") return;
|
||
|
|
|
||
|
|
const section = document.querySelector(".outfit-controls-section");
|
||
|
|
if (!section) return;
|
||
|
|
|
||
|
|
const searchInput = section.querySelector('.search-form input[type="text"]');
|
||
|
|
if (!searchInput) return;
|
||
|
|
|
||
|
|
// Collect all focusable item inputs in the results list.
|
||
|
|
const itemInputs = [
|
||
|
|
...section.querySelectorAll(
|
||
|
|
'.search-results-list item-card input[type="checkbox"]',
|
||
|
|
),
|
||
|
|
];
|
||
|
|
if (itemInputs.length === 0) return;
|
||
|
|
|
||
|
|
const allTargets = [searchInput, ...itemInputs];
|
||
|
|
const currentIndex = allTargets.indexOf(document.activeElement);
|
||
|
|
if (currentIndex === -1) return;
|
||
|
|
|
||
|
|
let nextIndex;
|
||
|
|
if (e.key === "ArrowDown") {
|
||
|
|
nextIndex = Math.min(currentIndex + 1, allTargets.length - 1);
|
||
|
|
} else {
|
||
|
|
nextIndex = Math.max(currentIndex - 1, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (nextIndex !== currentIndex) {
|
||
|
|
e.preventDefault();
|
||
|
|
allTargets[nextIndex].focus();
|
||
|
|
}
|
||
|
|
});
|