From 9d3bc0d43179b8e800046761eece221d0b64a508 Mon Sep 17 00:00:00 2001 From: leekeh <71131586+leekeh@users.noreply.github.com> Date: Tue, 4 Aug 2026 21:00:22 +0200 Subject: [PATCH 01/12] fix: better a11y for PackageSelector (use combobox pattern) --- app/components/Compare/PackageSelector.vue | 37 ++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/app/components/Compare/PackageSelector.vue b/app/components/Compare/PackageSelector.vue index a37978d7ff..2a5a001068 100644 --- a/app/components/Compare/PackageSelector.vue +++ b/app/components/Compare/PackageSelector.vue @@ -10,6 +10,10 @@ const props = defineProps<{ const maxPackages = computed(() => props.max ?? MAX_PACKAGE_SELECTION) +// Generate unique IDs for accessibility (prevents collisions when multiple instances mount) +const inputId = useId() +const listboxId = `${inputId}-listbox` + // Input state const inputValue = shallowRef('') const isInputFocused = shallowRef(false) @@ -175,6 +179,14 @@ function handleKeydown(e: KeyboardEvent) { } } +const activeDescendantId = computed(() => + highlightedIndex.value >= 0 ? `${listboxId}-option-${highlightedIndex.value}` : undefined, +) + +const showDropdown = computed( + () => isInputFocused.value && (navigableItems.value.length > 0 || isSearching.value), +) + // Reset highlight when user types watch(inputValue, () => { highlightedIndex.value = -1 @@ -200,8 +212,8 @@ onClickOutside(containerRef, () => {