impress/app/assets/javascripts/wardrobe/item-search-keys.js

61 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();
}
});