Fix opacity for excluded transactions and implement keyboard navigation (#1332)

* Make category selection menus opaque for excluded transactions

* Allow keyboard navigation in category selection menu

* Fix category transparency on mobile

* Make checkbox opaque

* Remove text-secondary from amount container

* Submit form directly

* Handle aria labels
This commit is contained in:
Mike Lloyd
2026-04-04 04:29:43 -07:00
committed by GitHub
parent 94e7f7f0a0
commit 281197f918
4 changed files with 100 additions and 13 deletions

View File

@@ -6,6 +6,8 @@ export default class extends Controller {
connect() {
this.inputTarget.focus();
this.highlightedIndex = -1;
this.updateAriaActiveDescendant();
}
filter() {
@@ -30,5 +32,82 @@ export default class extends Controller {
if (noMatchFound && this.hasEmptyMessageTarget) {
this.emptyMessageTarget.classList.remove("hidden");
}
this.highlightedIndex = -1;
this.clearHighlights();
this.updateAriaActiveDescendant();
}
handleKeydown(event) {
if (event.key === "ArrowDown") {
event.preventDefault();
this.highlightNext();
} else if (event.key === "ArrowUp") {
event.preventDefault();
this.highlightPrevious();
} else if (event.key === "Enter") {
event.preventDefault();
this.selectHighlighted();
}
}
highlightNext() {
const items = this.visibleItems;
if (items.length === 0) return;
this.clearHighlights();
this.highlightedIndex = Math.min(this.highlightedIndex + 1, items.length - 1);
this.highlightItem(items[this.highlightedIndex]);
this.updateAriaActiveDescendant();
}
highlightPrevious() {
const items = this.visibleItems;
if (items.length === 0) return;
this.clearHighlights();
this.highlightedIndex = Math.max(this.highlightedIndex - 1, 0);
this.highlightItem(items[this.highlightedIndex]);
this.updateAriaActiveDescendant();
}
highlightItem(item) {
item.classList.add("bg-container-inset-hover");
item.setAttribute("aria-selected", "true");
item.scrollIntoView({ block: "nearest" });
}
clearHighlights() {
this.listTarget.querySelectorAll(".filterable-item").forEach((item) => {
item.classList.remove("bg-container-inset-hover");
item.setAttribute("aria-selected", "false");
});
}
selectHighlighted() {
const items = this.visibleItems;
if (this.highlightedIndex < 0 || this.highlightedIndex >= items.length) return;
const item = items[this.highlightedIndex];
const form = item.querySelector("form");
if (form) {
form.requestSubmit();
}
}
updateAriaActiveDescendant() {
const items = this.visibleItems;
if (this.highlightedIndex >= 0 && this.highlightedIndex < items.length) {
const item = items[this.highlightedIndex];
this.inputTarget.setAttribute("aria-activedescendant", item.id);
} else {
this.inputTarget.removeAttribute("aria-activedescendant");
}
}
get visibleItems() {
return Array.from(this.listTarget.querySelectorAll(".filterable-item")).filter(
(item) => item.style.display !== "none"
);
}
}