Skip to content

Commit 3186091

Browse files
Dayifourautofix-ci[bot]knowler
authored
fix(a11y): improve facet selector accessibility (#1536)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Nathan Knowler <nathan@knowler.dev>
1 parent 5aff68f commit 3186091

30 files changed

+128
-147
lines changed

app/components/Compare/FacetSelector.vue

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
import { debounce } from 'perfect-debounce'
23
const {
34
isFacetSelected,
45
toggleFacet,
@@ -22,61 +23,94 @@ function isCategoryNoneSelected(category: string): boolean {
2223
const selectableFacets = facets.filter(f => !f.comingSoon)
2324
return selectableFacets.length > 0 && selectableFacets.every(f => !isFacetSelected(f.id))
2425
}
26+
27+
const liveRegionText = ref('')
28+
const clearLiveRegion = debounce(() => {
29+
liveRegionText.value = ''
30+
}, 250)
31+
const updateLiveRegion = debounce((message: string) => {
32+
liveRegionText.value = message
33+
clearLiveRegion()
34+
}, 250)
35+
36+
function selectAllFacet(category: string) {
37+
if (!isCategoryAllSelected(category)) {
38+
updateLiveRegion($t('compare.facets.selected_all_category_facets', { category }))
39+
selectCategory(category)
40+
}
41+
}
42+
43+
function deselectAllFacet(category: string) {
44+
if (!isCategoryNoneSelected(category)) {
45+
updateLiveRegion($t('compare.facets.deselected_all_category_facets', { category }))
46+
deselectCategory(category)
47+
}
48+
}
2549
</script>
2650

2751
<template>
28-
<div class="space-y-3" role="group" :aria-label="$t('compare.facets.group_label')">
52+
<div role="status" aria-live="polite" class="sr-only">{{ liveRegionText }}</div>
53+
<div class="space-y-3">
2954
<div v-for="category in categoryOrder" :key="category">
30-
<!-- Category header with all/none buttons -->
3155
<div class="flex items-center gap-2 mb-2">
32-
<span class="text-3xs text-fg-subtle uppercase tracking-wider">
56+
<span
57+
:id="`facet-category-label-${category}`"
58+
class="text-3xs text-fg-subtle uppercase tracking-wider"
59+
>
3360
{{ getCategoryLabel(category) }}
3461
</span>
35-
<!-- TODO: These should be radios, since they are mutually exclusive, and currently this behavior is faked with buttons -->
62+
3663
<ButtonBase
64+
size="sm"
65+
data-facet-category-action="all"
66+
:data-facet-category="category"
3767
:aria-label="
38-
$t('compare.facets.select_category', { category: getCategoryLabel(category) })
68+
$t('compare.facets.select_all_category_facets', {
69+
category: getCategoryLabel(category),
70+
})
3971
"
40-
:aria-pressed="isCategoryAllSelected(category)"
41-
:disabled="isCategoryAllSelected(category)"
42-
@click="selectCategory(category)"
43-
size="sm"
72+
:aria-disabled="isCategoryAllSelected(category)"
73+
class="aria-disabled:(opacity-40 border-transparent)"
74+
@click="selectAllFacet(category)"
4475
>
4576
{{ $t('compare.facets.all') }}
4677
</ButtonBase>
47-
<span class="text-2xs text-fg-muted/40">/</span>
78+
79+
<span class="text-2xs text-fg-muted/40" aria-hidden="true">/</span>
80+
4881
<ButtonBase
82+
size="sm"
83+
data-facet-category-action="none"
84+
:data-facet-category="category"
4985
:aria-label="
50-
$t('compare.facets.deselect_category', { category: getCategoryLabel(category) })
86+
$t('compare.facets.deselect_all_category_facets', {
87+
category: getCategoryLabel(category),
88+
})
5189
"
52-
:aria-pressed="isCategoryNoneSelected(category)"
53-
:disabled="isCategoryNoneSelected(category)"
54-
@click="deselectCategory(category)"
55-
size="sm"
90+
:aria-disabled="isCategoryNoneSelected(category)"
91+
class="aria-disabled:(opacity-40 border-transparent)"
92+
@click="deselectAllFacet(category)"
5693
>
5794
{{ $t('compare.facets.none') }}
5895
</ButtonBase>
5996
</div>
6097

61-
<!-- Facet buttons -->
62-
<div class="flex items-center gap-1.5 flex-wrap" role="group">
63-
<!-- TODO: These should be checkboxes -->
98+
<div
99+
class="flex items-center gap-1.5 flex-wrap"
100+
role="group"
101+
:aria-labelledby="`facet-category-label-${category}`"
102+
data-facet-category-facets
103+
>
64104
<ButtonBase
65105
v-for="facet in facetsByCategory[category]"
66106
:key="facet.id"
67107
size="sm"
108+
role="checkbox"
68109
:title="facet.comingSoon ? $t('compare.facets.coming_soon') : facet.description"
69110
:disabled="facet.comingSoon"
70-
:aria-pressed="isFacetSelected(facet.id)"
111+
:aria-checked="isFacetSelected(facet.id)"
71112
:aria-label="facet.label"
72-
class="gap-1 px-1.5 rounded transition-colors focus-visible:outline-accent/70"
73-
:class="
74-
facet.comingSoon
75-
? 'text-fg-subtle/50 bg-bg-subtle border-border-subtle cursor-not-allowed'
76-
: isFacetSelected(facet.id)
77-
? 'text-fg-muted bg-bg-muted'
78-
: 'text-fg-subtle bg-bg-subtle border-border-subtle hover:text-fg-muted hover:border-border'
79-
"
113+
class="gap-1 px-1.5 rounded transition-colors text-fg-subtle bg-bg-subtle border-border-subtle enabled:hover:(text-fg-muted border-border) aria-checked:(text-fg-muted bg-fg/10 border-fg/20 hover:enabled:(bg-fg/20 text-fg/50)) focus-visible:outline-accent/70 disabled:(text-fg-subtle/50 bg-bg-subtle border-border-subtle)"
80114
@click="!facet.comingSoon && toggleFacet(facet.id)"
81115
:classicon="
82116
facet.comingSoon

i18n/locales/ar.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -937,14 +937,11 @@
937937
"add_column": "إضافة عمود «بدون تبعية» إلى المقارنة"
938938
},
939939
"facets": {
940-
"group_label": "محاور المقارنة",
941940
"all": "الكل",
942941
"none": "لا شيء",
943942
"coming_soon": "قريبًا",
944943
"select_all": "تحديد كل المحاور",
945944
"deselect_all": "إلغاء تحديد كل المحاور",
946-
"select_category": "تحديد جميع محاور {category}",
947-
"deselect_category": "إلغاء تحديد جميع محاور {category}",
948945
"binary_only_tooltip": "هذه الحزمة تعرض ملفات تنفيذية فقط دون تصديرات",
949946
"categories": {
950947
"performance": "الأداء",

i18n/locales/az-AZ.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1051,14 +1051,11 @@
10511051
"add_column": "Müqayisəyə asılılıqsız sütun əlavə et"
10521052
},
10531053
"facets": {
1054-
"group_label": "Müqayisə aspektləri",
10551054
"all": "hamısı",
10561055
"none": "heç biri",
10571056
"coming_soon": "Tezliklə",
10581057
"select_all": "Bütün aspektləri seç",
10591058
"deselect_all": "Bütün aspektləri ləğv et",
1060-
"select_category": "Bütün {category} aspektlərini seç",
1061-
"deselect_category": "Bütün {category} aspektlərini ləğv et",
10621059
"binary_only_tooltip": "Bu paket yalnız binar fayllar təqdim edir, ixrac yoxdur",
10631060
"categories": {
10641061
"performance": "Performans",

i18n/locales/bg-BG.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,14 +1008,11 @@
10081008
"add_column": "Добавяне на колона без зависимости към сравнението"
10091009
},
10101010
"facets": {
1011-
"group_label": "Аспекти на сравнението",
10121011
"all": "всички",
10131012
"none": "нито един",
10141013
"coming_soon": "Скоро",
10151014
"select_all": "Избор на всички аспекти",
10161015
"deselect_all": "Отмяна на избора на всички аспекти",
1017-
"select_category": "Избор на всички {category} аспекти",
1018-
"deselect_category": "Отмяна на избора на всички {category} аспекти",
10191016
"binary_only_tooltip": "Този пакет излага binaries и няма exports",
10201017
"categories": {
10211018
"performance": "Производителност",

i18n/locales/bn-IN.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -807,14 +807,11 @@
807807
},
808808
"no_dependency": {},
809809
"facets": {
810-
"group_label": "তুলনা ফ্যাসেট",
811810
"all": "সব",
812811
"none": "কিছু না",
813812
"coming_soon": "শীঘ্রই আসছে",
814813
"select_all": "সব ফ্যাসেট নির্বাচন করুন",
815814
"deselect_all": "সব ফ্যাসেট অনির্বাচিত করুন",
816-
"select_category": "সব {category} ফ্যাসেট নির্বাচন করুন",
817-
"deselect_category": "সব {category} ফ্যাসেট অনির্বাচিত করুন",
818815
"categories": {
819816
"performance": "কর্মক্ষমতা",
820817
"health": "স্বাস্থ্য",

i18n/locales/cs-CZ.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,14 +1065,11 @@
10651065
"add_column": "Přidat sloupec bez závislosti do porovnání"
10661066
},
10671067
"facets": {
1068-
"group_label": "Kategorie vlastností",
10691068
"all": "Vše",
10701069
"none": "Žádné",
10711070
"coming_soon": "Brzy k dispozici",
10721071
"select_all": "Vybrat všechny vlastnosti",
10731072
"deselect_all": "Zrušit výběr všech vlastností",
1074-
"select_category": "Vybrat všechny vlastnosti kategorie {category}",
1075-
"deselect_category": "Zrušit výběr všech vlastností kategorie {category}",
10761073
"binary_only_tooltip": "Tento balíček obsahuje pouze binární soubory a žádné exporty",
10771074
"categories": {
10781075
"performance": "Výkon",

i18n/locales/de.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,14 +1127,11 @@
11271127
"add_column": "Spalte „Keine Abhängigkeit“ zum Vergleich hinzufügen"
11281128
},
11291129
"facets": {
1130-
"group_label": "Vergleichsfacetten",
11311130
"all": "Alle",
11321131
"none": "Keine",
11331132
"coming_soon": "Demnächst verfügbar",
11341133
"select_all": "Alle Facetten auswählen",
11351134
"deselect_all": "Alle Facetten abwählen",
1136-
"select_category": "Alle {category}-Facetten auswählen",
1137-
"deselect_category": "Alle {category}-Facetten abwählen",
11381135
"binary_only_tooltip": "Dieses Paket stellt Binärdateien bereit und hat keine Exports",
11391136
"categories": {
11401137
"performance": "Performance",

i18n/locales/en.json

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,14 +1128,15 @@
11281128
"add_column": "Add no dependency column to comparison"
11291129
},
11301130
"facets": {
1131-
"group_label": "Comparison facets",
11321131
"all": "all",
11331132
"none": "none",
1133+
"select_all_category_facets": "Select all {category} facets",
1134+
"deselect_all_category_facets": "Deselect all {category} facets",
1135+
"selected_all_category_facets": "Selected all {category} facets",
1136+
"deselected_all_category_facets": "Deselected all {category} facets",
11341137
"coming_soon": "Coming soon",
11351138
"select_all": "Select all facets",
11361139
"deselect_all": "Deselect all facets",
1137-
"select_category": "Select all {category} facets",
1138-
"deselect_category": "Deselect all {category} facets",
11391140
"binary_only_tooltip": "This package exposes binaries and no exports",
11401141
"categories": {
11411142
"performance": "Performance",

i18n/locales/es.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,14 +1072,11 @@
10721072
"add_column": "Añadir columna sin dependencia a la comparación"
10731073
},
10741074
"facets": {
1075-
"group_label": "Facetas de comparación",
10761075
"all": "todas",
10771076
"none": "ninguna",
10781077
"coming_soon": "Próximamente",
10791078
"select_all": "Seleccionar todas las facetas",
10801079
"deselect_all": "Deseleccionar todas las facetas",
1081-
"select_category": "Seleccionar todas las facetas de {category}",
1082-
"deselect_category": "Deseleccionar todas las facetas de {category}",
10831080
"binary_only_tooltip": "Este paquete expone binarios y no exportaciones",
10841081
"categories": {
10851082
"performance": "Rendimiento",

i18n/locales/fr-FR.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,14 +1125,11 @@
11251125
"add_column": "Ajouter la colonne sans dépendance à la comparaison"
11261126
},
11271127
"facets": {
1128-
"group_label": "Facettes de comparaison",
11291128
"all": "tout",
11301129
"none": "aucun",
11311130
"coming_soon": "Bientôt disponible",
11321131
"select_all": "Sélectionner toutes les facettes",
11331132
"deselect_all": "Désélectionner toutes les facettes",
1134-
"select_category": "Sélectionner toutes les facettes {category}",
1135-
"deselect_category": "Désélectionner toutes les facettes {category}",
11361133
"binary_only_tooltip": "Ce paquet expose des binaires et aucun export",
11371134
"categories": {
11381135
"performance": "Performance",

0 commit comments

Comments
 (0)